def test_salt_object(self): def attr_fail(): Salt.fail.blah() def times2(x): return x * 2 __salt__ = {'math.times2': times2} Salt = SaltObject(__salt__) self.assertRaises(AttributeError, attr_fail) self.assertEqual(Salt.math.times2, times2) self.assertEqual(Salt.math.times2(2), 4)
def render(template, saltenv='base', sls='', salt_data=True, **kwargs): if 'pyobjects_states' not in __context__: load_states() # these hold the scope that our sls file will be executed with _globals = {} # create our StateFactory objects mod_globals = {'StateFactory': StateFactory} for mod in __context__['pyobjects_states']: mod_locals = {} mod_camel = ''.join([part.capitalize() for part in mod.split('_')]) valid_funcs = "','".join(__context__['pyobjects_states'][mod]) mod_cmd = "{0} = StateFactory('{1!s}', valid_funcs=['{2}'])".format( mod_camel, mod, valid_funcs) exec_(mod_cmd, mod_globals, mod_locals) _globals[mod_camel] = mod_locals[mod_camel] # add our include and extend functions _globals['include'] = Registry.include _globals['extend'] = Registry.make_extend # add our map class Map.__salt__ = __salt__ _globals['Map'] = Map # add some convenience methods to the global scope as well as the "dunder" # format of all of the salt objects try: _globals.update({ # salt, pillar & grains all provide shortcuts or object interfaces 'salt': SaltObject(__salt__), 'pillar': __salt__['pillar.get'], 'grains': __salt__['grains.get'], 'mine': __salt__['mine.get'], 'config': __salt__['config.get'], # the "dunder" formats are still available for direct use '__salt__': __salt__, '__pillar__': __pillar__, '__grains__': __grains__ }) except NameError: pass # if salt_data is not True then we just return the global scope we've # built instead of returning salt data from the registry if not salt_data: return _globals # this will be used to fetch any import files client = get_file_client(__opts__) # process our sls imports # # we allow pyobjects users to use a special form of the import statement # so that they may bring in objects from other files. while we do this we # disable the registry since all we're looking for here is python objects, # not salt state data template_data = [] Registry.enabled = False for line in template.readlines(): line = line.rstrip('\r\n') matched = False for RE in (IMPORT_RE, FROM_RE): matches = RE.match(line) if not matches: continue import_file = matches.group(1).strip() try: imports = matches.group(2).split(',') except IndexError: # if we don't have a third group in the matches object it means # that we're importing everything imports = None state_file = client.cache_file(import_file, saltenv) if not state_file: raise ImportError( "Could not find the file {0!r}".format(import_file)) with salt.utils.fopen(state_file) as f: state_contents = f.read() state_locals = {} exec_(state_contents, _globals, state_locals) if imports is None: imports = list(state_locals) for name in imports: name = alias = name.strip() matches = FROM_AS_RE.match(name) if matches is not None: name = matches.group(1).strip() alias = matches.group(2).strip() if name not in state_locals: raise ImportError("{0!r} was not found in {1!r}".format( name, import_file)) _globals[alias] = state_locals[name] matched = True break if not matched: template_data.append(line) final_template = "\n".join(template_data) # re-enable the registry Registry.enabled = True # now exec our template using our created scopes exec_(final_template, _globals) return Registry.salt_data()
def render(template, saltenv='base', sls='', tmplpath=None, rendered_sls=None, _states=None, **kwargs): _globals = {} _locals = {} _registry = StateRegistry() if _states is None: try: _states = __states__ except NameError: from salt.loader import states __opts__['grains'] = __grains__ __opts__['pillar'] = __pillar__ _states = states(__opts__, __salt__) # build our list of states and functions _st_funcs = {} for func in _states: (mod, func) = func.split(".") if mod not in _st_funcs: _st_funcs[mod] = [] _st_funcs[mod].append(func) # create our StateFactory objects _st_globals = {'StateFactory': StateFactory, '_registry': _registry} for mod in _st_funcs: _st_locals = {} _st_funcs[mod].sort() mod_camel = ''.join([part.capitalize() for part in mod.split('_')]) mod_cmd = "%s = StateFactory('%s', registry=_registry, valid_funcs=['%s'])" % ( mod_camel, mod, "','".join(_st_funcs[mod])) if sys.version > 3: exec(mod_cmd, _st_globals, _st_locals) else: exec mod_cmd in _st_globals, _st_locals _globals[mod_camel] = _st_locals[mod_camel] # add our Include and Extend functions _globals['include'] = _registry.include _globals['extend'] = _registry.make_extend # for convenience try: _globals.update({ # salt, pillar & grains all provide shortcuts or object interfaces 'salt': SaltObject(__salt__), 'pillar': __salt__['pillar.get'], 'grains': __salt__['grains.get'], 'mine': __salt__['mine.get'], # the "dunder" formats are still available for direct use '__salt__': __salt__, '__pillar__': __pillar__, '__grains__': __grains__ }) except NameError: pass if sys.version > 3: exec(template.read(), _globals, _locals) else: exec template.read() in _globals, _locals return _registry.salt_data()
def render(template, saltenv='base', sls='', **kwargs): if 'pyobjects_states' not in __context__: load_states() # these hold the scope that our sls file will be executed with _globals = {} _locals = {} # this will be used to fetch any import files client = get_file_client(__opts__) # create our StateFactory objects mod_globals = {'StateFactory': StateFactory} for mod in __context__['pyobjects_states']: mod_locals = {} mod_camel = ''.join([part.capitalize() for part in mod.split('_')]) valid_funcs = "','".join(__context__['pyobjects_states'][mod].keys()) mod_cmd = "{0} = StateFactory('{1!s}', valid_funcs=['{2}'])".format( mod_camel, mod, valid_funcs) if sys.version_info[0] > 2: # in py3+ exec is a function exec(mod_cmd, mod_globals, mod_locals) else: # prior to that it is a statement exec mod_cmd in mod_globals, mod_locals _globals[mod_camel] = mod_locals[mod_camel] # add our include and extend functions _globals['include'] = Registry.include _globals['extend'] = Registry.make_extend # add our map class Map.__salt__ = __salt__ _globals['Map'] = Map # add some convenience methods to the global scope as well as the "dunder" # format of all of the salt objects try: _globals.update({ # salt, pillar & grains all provide shortcuts or object interfaces 'salt': SaltObject(__salt__), 'pillar': __salt__['pillar.get'], 'grains': __salt__['grains.get'], 'mine': __salt__['mine.get'], # the "dunder" formats are still available for direct use '__salt__': __salt__, '__pillar__': __pillar__, '__grains__': __grains__ }) except NameError: pass # process our sls imports # # we allow pyobjects users to use a special form of the import statement # so that they may bring in objects from other files. while we do this we # disable the registry since all we're looking for here is python objects, # not salt state data # # once we have our template we scan through it and look for any "from X # import Y" statements and if X ends in .sls then we process it by passing # the file in X through the pyobjects renderer and putting the requested # variables into our template template_data = [] Registry.enabled = False for line in template.readlines(): line = line.rstrip('\r\n') matched = False for RE in (IMPORT_RE, FROM_RE): matches = re.match(RE, line) if not matches: continue import_file = matches.group(1).strip() try: imports = matches.group(2).split(',') except IndexError: # if we don't have a third group in the matches object it means # that we're importing everything imports = None state_file = client.cache_file(import_file, saltenv) if not state_file: raise ImportError( "Could not find the file {0!r}".format(import_file)) with open(state_file) as f: state_contents = f.read() state_locals = {} if sys.version_info[0] > 2: # in py3+ exec is a function exec(state_contents, _globals, state_locals) else: # prior to that it is a statement exec state_contents in _globals, state_locals if imports is None: imports = state_locals.keys() for name in imports: name = name.strip() if name not in state_locals: raise ImportError("{0!r} was not found in {1!r}".format( name, import_file)) _globals[name] = state_locals[name] matched = True break if not matched: template_data.append(line) final_template = "\n".join(template_data) # re-enable the registry Registry.enabled = True # now exec our template using our created scopes if sys.version_info[0] > 2: # in py3+ exec is a function exec(final_template, _globals, _locals) else: # prior to that it is a statement exec final_template in _globals, _locals return Registry.salt_data()
def render(template, saltenv="base", sls="", salt_data=True, **kwargs): if "pyobjects_states" not in __context__: load_states() # these hold the scope that our sls file will be executed with _globals = {} # create our StateFactory objects mod_globals = {"StateFactory": StateFactory} for mod in __context__["pyobjects_states"]: mod_locals = {} mod_camel = "".join([part.capitalize() for part in mod.split("_")]) valid_funcs = "','".join(__context__["pyobjects_states"][mod]) mod_cmd = "{} = StateFactory('{!s}', valid_funcs=['{}'])".format( mod_camel, mod, valid_funcs) exec(mod_cmd, mod_globals, mod_locals) _globals[mod_camel] = mod_locals[mod_camel] # add our include and extend functions _globals["include"] = Registry.include _globals["extend"] = Registry.make_extend # add our map class Map.__salt__ = __salt__ _globals["Map"] = Map # add some convenience methods to the global scope as well as the "dunder" # format of all of the salt objects try: _globals.update({ # salt, pillar & grains all provide shortcuts or object interfaces "salt": SaltObject(__salt__), "pillar": __salt__["pillar.get"], "grains": __salt__["grains.get"], "mine": __salt__["mine.get"], "config": __salt__["config.get"], # the "dunder" formats are still available for direct use "__salt__": __salt__, "__pillar__": __pillar__, "__grains__": __grains__, "__opts__": __opts__, "__sls__": sls, }) except NameError: pass # if salt_data is not True then we just return the global scope we've # built instead of returning salt data from the registry if not salt_data: return _globals # this will be used to fetch any import files client = get_file_client(__opts__) # process our sls imports # # we allow pyobjects users to use a special form of the import statement # so that they may bring in objects from other files. while we do this we # disable the registry since all we're looking for here is python objects, # not salt state data Registry.enabled = False def process_template(template): template_data = [] # Do not pass our globals to the modules we are including and keep the root _globals untouched template_globals = dict(_globals) for line in template.readlines(): line = line.rstrip("\r\n") matched = False for RE in (IMPORT_RE, FROM_RE): matches = RE.match(line) if not matches: continue import_file = matches.group(1).strip() try: imports = matches.group(2).split(",") except IndexError: # if we don't have a third group in the matches object it means # that we're importing everything imports = None state_file = client.cache_file(import_file, saltenv) if not state_file: raise ImportError( "Could not find the file '{}'".format(import_file)) with salt.utils.files.fopen(state_file) as state_fh: state_contents, state_globals = process_template(state_fh) exec(state_contents, state_globals) # if no imports have been specified then we are being imported as: import salt://foo.sls # so we want to stick all of the locals from our state file into the template globals # under the name of the module -> i.e. foo.MapClass if imports is None: import_name = os.path.splitext( os.path.basename(state_file))[0] template_globals[import_name] = PyobjectsModule( import_name, state_globals) else: for name in imports: name = alias = name.strip() matches = FROM_AS_RE.match(name) if matches is not None: name = matches.group(1).strip() alias = matches.group(2).strip() if name not in state_globals: raise ImportError( "'{}' was not found in '{}'".format( name, import_file)) template_globals[alias] = state_globals[name] matched = True break if not matched: template_data.append(line) return "\n".join(template_data), template_globals # process the template that triggered the render final_template, final_globals = process_template(template) _globals.update(final_globals) # re-enable the registry Registry.enabled = True # now exec our template using our created scopes exec(final_template, _globals) return Registry.salt_data()
def render(template, saltenv='base', sls='', tmplpath=None, rendered_sls=None, _states=None, **kwargs): # these hold the scope that our sls file will be executed with _globals = {} _locals = {} # create our registry _registry = StateRegistry() # if we haven't been provided a list of states (which really only happens # from the tests) then try to use the __states__ global that the renderer # loader should provide (see commit cc8539f), if the global doesn't exist # (also usually from the tests) then we load the states ourself if _states is None: try: _states = __states__ except NameError: from salt.loader import states __opts__['grains'] = __grains__ __opts__['pillar'] = __pillar__ _states = states(__opts__, __salt__) # build our list of states and functions that we will use to build our # StateFactory objects _st_funcs = {} for func in _states: (mod, func) = func.split(".") if mod not in _st_funcs: _st_funcs[mod] = [] _st_funcs[mod].append(func) # create our StateFactory objects _st_globals = {'StateFactory': StateFactory, '_registry': _registry} for mod in _st_funcs: _st_locals = {} _st_funcs[mod].sort() mod_camel = ''.join([ part.capitalize() for part in mod.split('_') ]) mod_cmd = "%s = StateFactory('%s', registry=_registry, valid_funcs=['%s'])" % ( mod_camel, mod, "','".join(_st_funcs[mod]) ) if sys.version > 3: exec(mod_cmd, _st_globals, _st_locals) else: exec mod_cmd in _st_globals, _st_locals _globals[mod_camel] = _st_locals[mod_camel] # add our include and extend functions _globals['include'] = _registry.include _globals['extend'] = _registry.make_extend # add some convenience methods to the global scope as well as the "dunder" # format of all of the salt objects try: _globals.update({ # salt, pillar & grains all provide shortcuts or object interfaces 'salt': SaltObject(__salt__), 'pillar': __salt__['pillar.get'], 'grains': __salt__['grains.get'], 'mine': __salt__['mine.get'], # the "dunder" formats are still available for direct use '__salt__': __salt__, '__pillar__': __pillar__, '__grains__': __grains__ }) except NameError: pass # now exec our template using our created scopes # in py3+ exec is a function, prior to that it is a statement if sys.version > 3: exec(template.read(), _globals, _locals) else: exec template.read() in _globals, _locals return _registry.salt_data()