From 3752742fa0632e1c9572a4b1372f56d248f44695 Mon Sep 17 00:00:00 2001 From: Dan Colish Date: Tue, 6 Mar 2012 20:42:01 -0800 Subject: [PATCH] Refactor common template code for pillar and states --- salt/pillar.py | 62 +++++++++++------------------------- salt/state.py | 82 ++++++++++++++---------------------------------- salt/template.py | 57 +++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 103 deletions(-) create mode 100644 salt/template.py diff --git a/salt/pillar.py b/salt/pillar.py index f909342d2b..edcb30ac9a 100644 --- a/salt/pillar.py +++ b/salt/pillar.py @@ -13,9 +13,13 @@ import salt.fileclient import salt.minion import salt.crypt +from salt.template import compile_template + + # Import third party libs import zmq + def get_pillar(opts, grains, id_, env=None): ''' Return the correct pillar driver based on the file_client option @@ -104,43 +108,6 @@ class Pillar(object): envs.update(self.opts['file_roots'].keys()) return envs - def template_shebang(self, template): - ''' - Check the template shebang line and return the renderer - ''' - # Open up the first line of the sls template - line = '' - with open(template, 'r') as f: - line = f.readline() - # Check if it starts with a shebang - if line.startswith('#!'): - # pull out the shebang data - trend = line.strip()[2:] - # If the specified renderer exists, use it, or fallback - if trend in self.rend: - return trend - return self.opts['renderer'] - - def compile_template(self, template, env='', sls=''): - ''' - Take the path to a template and return the high data structure - derived from the template. - ''' - # Template was specified incorrectly - if not isinstance(template, basestring): - return {} - # Template does not exists - if not os.path.isfile(template): - return {} - # Template is an empty file - if salt.utils.is_empty(template): - return {} - # Template is nothing but whitespace - if not open(template).read().strip(): - return {} - - return self.rend[self.template_shebang(template)](template, env, sls) - def get_tops(self): ''' Gather the top files @@ -151,23 +118,27 @@ class Pillar(object): # Gather initial top files if self.opts['environment']: tops[self.opts['environment']] = [ - self.compile_template( + compile_template( self.client.cache_file( self.opts['state_top'], self.opts['environment'] ), + self.rend, + self.opts['renderer'], self.opts['environment'] ) ] else: for env in self._get_envs(): tops[env].append( - self.compile_template( + compile_template( self.client.cache_file( self.opts['state_top'], env ), - env + self.rend, + self.opts['renderer'], + env=env ) ) @@ -190,12 +161,14 @@ class Pillar(object): if sls in done[env]: continue tops[env].append( - self.compile_template( + compile_template( self.client.get_state( sls, env ), - env + self.rend, + self.opts['renderer'], + env=env ) ) done[env].append(sls) @@ -286,7 +259,8 @@ class Pillar(object): ' available on the salt master').format(sls, env)) state = None try: - state = self.compile_template(fn_, env, sls) + state = compile_template( + fn_, self.rend, self.opts['renderer'], env, sls) except Exception as exc: errors.append(('Rendering SLS {0} failed, render error:\n{1}' .format(sls, exc))) @@ -332,7 +306,7 @@ class Pillar(object): if err: errors += err return pillar, errors - + def compile_pillar(self): ''' diff --git a/salt/state.py b/salt/state.py index 57f9c2d76c..760c516a6b 100644 --- a/salt/state.py +++ b/salt/state.py @@ -17,7 +17,6 @@ import copy import inspect import fnmatch import logging -import tempfile import collections # Import Salt Libs @@ -26,6 +25,11 @@ import salt.loader import salt.minion import salt.fileclient +from salt.template import ( + compile_template, + compile_template_str, + template_shebang, + ) log = logging.getLogger(__name__) @@ -527,55 +531,6 @@ class State(object): high[name][state].append(arg) return high, errors - def template_shebang(self, template): - ''' - Check the template shebang line and return the renderer - ''' - # Open up the first line of the sls template - line = '' - with open(template, 'r') as f: - line = f.readline() - # Check if it starts with a shebang - if line.startswith('#!'): - # pull out the shebang data - trend = line.strip()[2:] - # If the specified renderer exists, use it, or fallback - if trend in self.rend: - return trend - return self.opts['renderer'] - - def compile_template(self, template, env='', sls=''): - ''' - Take the path to a template and return the high data structure - derived from the template. - ''' - # Template was specified incorrectly - if not isinstance(template, basestring): - return {} - # Template does not exists - if not os.path.isfile(template): - return {} - # Template is an empty file - if salt.utils.is_empty(template): - return {} - # Template is nothing but whitespace - if not open(template).read().strip(): - return {} - - return self.rend[self.template_shebang(template)](template, env, sls) - - def compile_template_str(self, template): - ''' - Take the path to a template and return the high data structure - derived from the template. - ''' - fn_ = tempfile.mkstemp()[1] - with open(fn_, 'w+') as f: - f.write(template) - high = self.rend[self.template_shebang(fn_)](fn_) - os.remove(fn_) - return high - def call(self, data): ''' Call a state directly with the low data structure, verify data @@ -776,7 +731,8 @@ class State(object): ''' Enforce the states in a template ''' - high = self.compile_template(template) + high = compile_template( + template, self.renderers, self.opts['renderer']) if high: return self.call_high(high) return high @@ -785,7 +741,8 @@ class State(object): ''' Enforce the states in a template, pass the template as a string ''' - high = self.compile_template_str(template) + high = compile_template_str( + template, self.renderers, self.opts['renderer']) if high: return self.call_high(high) return high @@ -846,23 +803,27 @@ class HighState(object): # Gather initial top files if self.opts['environment']: tops[self.opts['environment']] = [ - self.state.compile_template( + compile_template( self.client.cache_file( self.opts['state_top'], self.opts['environment'] ), - self.opts['environment'] + self.state.rend, + self.state.opts['renderer'], + env=self.opts['environment'] ) ] else: for env in self._get_envs(): tops[env].append( - self.state.compile_template( + compile_template( self.client.cache_file( self.opts['state_top'], env ), - env + self.state.rend, + self.state.opts['renderer'], + env=env ) ) @@ -885,12 +846,14 @@ class HighState(object): if sls in done[env]: continue tops[env].append( - self.state.compile_template( + compile_template( self.client.get_state( sls, env ), - env + self.state.rend, + self.state.opts['renderer'], + env=env ) ) done[env].append(sls) @@ -1006,7 +969,8 @@ class HighState(object): ' available on the salt master').format(sls, env)) state = None try: - state = self.state.compile_template(fn_, env, sls) + state = compile_template( + fn_, self.state.rend, self.state.opts['renderer'], env, sls) except Exception as exc: errors.append(('Rendering SLS {0} failed, render error:\n{1}' .format(sls, exc))) diff --git a/salt/template.py b/salt/template.py new file mode 100644 index 0000000000..b803e8f6a4 --- /dev/null +++ b/salt/template.py @@ -0,0 +1,57 @@ +import os.path +import tempfile + +import salt.utils + + +def compile_template(template, renderers, default, env='', sls=''): + ''' + Take the path to a template and return the high data structure + derived from the template. + ''' + # Template was specified incorrectly + if not isinstance(template, basestring): + return {} + # Template does not exists + if not os.path.isfile(template): + return {} + # Template is an empty file + if salt.utils.is_empty(template): + return {} + # Template is nothing but whitespace + with open(template) as f: + if not f.read().strip(): + return {} + return renderers[ + template_shebang(template, renderers, default)](template, env, sls) + + +def compile_template_str(template, renderers, default): + ''' + Take the path to a template and return the high data structure + derived from the template. + ''' + fn_ = tempfile.mkstemp()[1] + with open(fn_, 'w+') as f: + f.write(template) + high = renderers[template_shebang(fn_, renderers, default)](fn_) + os.remove(fn_) + return high + + +def template_shebang(template, renderers, default): + ''' + Check the template shebang line and return the renderer + ''' + # Open up the first line of the sls template + line = '' + with open(template, 'r') as f: + line = f.readline() + # Check if it starts with a shebang + if line.startswith('#!'): + # pull out the shebang data + trend = line.strip()[2:] + # If the specified renderer exists, use it, or fallback + if trend in renderers: + return trend + return default