def create_file(self): try: desc_template = NativeEnvironment().from_string( self.tentacle_creator.get_templates()["Description"]) impl_template = NativeEnvironment().from_string( self.tentacle_creator.get_templates()[self.subtype]) if not os.path.isfile(self.get_path()): with open(self.get_path(), "w") as tentacle_file: tentacle_file.write(self.header_separator) tentacle_file.write( desc_template.render(name=self.name, big_name=self.name.title(), t_type=self.t_type, subtype=self.subtype, version=self.version, requirements=self.requirements, tests=self.tests, config=self.config_file)) tentacle_file.write("\n" + self.header_separator) tentacle_file.write( impl_template.render(name=self.name, big_name=self.name.title(), t_type=self.t_type, subtype=self.subtype, version=self.version, requirements=self.requirements, tests=self.tests, config=self.config_file)) # TODO add __init__.py management else: raise Exception("A tentacle with this name already exists") except Exception as e: raise e
def create_config_file(self): try: cfg_template = NativeEnvironment().from_string( self.tentacle_creator.get_config_templates()[self.subtype]) if not os.path.isfile(self.get_config_path()): with open(self.get_config_path(), "w") as config_file: config_file.write(cfg_template.render()[1:]) else: raise Exception("A config with this name already exists") except Exception: pass
def get_config_value_and_origin(self, config, cfile=None, plugin_type=None, plugin_name=None, keys=None, variables=None, direct=None): ''' Given a config key figure out the actual value and report on the origin of the settings ''' if cfile is None: # use default config cfile = self._config_file if config == 'CONFIG_FILE': return cfile, '' # Note: sources that are lists listed in low to high precedence (last one wins) value = None origin = None defs = self.get_configuration_definitions(plugin_type, plugin_name) if config in defs: aliases = defs[config].get('aliases', []) # direct setting via plugin arguments, can set to None so we bypass rest of processing/defaults if direct: if config in direct: value = direct[config] origin = 'Direct' else: direct_aliases = [ direct[alias] for alias in aliases if alias in direct ] if direct_aliases: value = direct_aliases[0] origin = 'Direct' if value is None and variables and defs[config].get('vars'): # Use 'variable overrides' if present, highest precedence, but only present when querying running play value, origin = self._loop_entries(variables, defs[config]['vars']) origin = 'var: %s' % origin # use playbook keywords if you have em if value is None and defs[config].get('keyword') and keys: value, origin = self._loop_entries(keys, defs[config]['keyword']) origin = 'keyword: %s' % origin # automap to keywords # TODO: deprecate these in favor of explicit keyword above if value is None and keys: if config in keys: value = keys[config] keyword = config elif aliases: for alias in aliases: if alias in keys: value = keys[alias] keyword = alias break if value is not None: origin = 'keyword: %s' % keyword if value is None and 'cli' in defs[config]: # avoid circular import .. until valid from ansible import context value, origin = self._loop_entries(context.CLIARGS, defs[config]['cli']) origin = 'cli: %s' % origin # env vars are next precedence if value is None and defs[config].get('env'): value, origin = self._loop_entries(py3compat.environ, defs[config]['env']) origin = 'env: %s' % origin # try config file entries next, if we have one if self._parsers.get(cfile, None) is None: self._parse_config_file(cfile) if value is None and cfile is not None: ftype = get_config_type(cfile) if ftype and defs[config].get(ftype): if ftype == 'ini': # load from ini config try: # FIXME: generalize _loop_entries to allow for files also, most of this code is dupe for ini_entry in defs[config]['ini']: temp_value = get_ini_config_value( self._parsers[cfile], ini_entry) if temp_value is not None: value = temp_value origin = cfile if 'deprecated' in ini_entry: self.DEPRECATED.append( ('[%s]%s' % (ini_entry['section'], ini_entry['key']), ini_entry['deprecated'])) except Exception as e: sys.stderr.write( "Error while loading ini config %s: %s" % (cfile, to_native(e))) elif ftype == 'yaml': # FIXME: implement, also , break down key from defs (. notation???) origin = cfile # set default if we got here w/o a value if value is None: if defs[config].get('required', False): if not plugin_type or config not in INTERNAL_DEFS.get( plugin_type, {}): raise AnsibleError( "No setting was provided for required configuration %s" % to_native( _get_entry(plugin_type, plugin_name, config))) else: origin = 'default' value = defs[config].get('default') if isinstance(value, string_types) and ( value.startswith('{{') and value.endswith('}}')) and variables is not None: # template default values if possible # NOTE: cannot use is_template due to circular dep try: t = NativeEnvironment().from_string(value) value = t.render(variables) except Exception: pass # not templatable # ensure correct type, can raise exceptions on mismatched types try: value = ensure_type(value, defs[config].get('type'), origin=origin) except ValueError as e: if origin.startswith('env:') and value == '': # this is empty env var for non string so we can set to default origin = 'default' value = ensure_type(defs[config].get('default'), defs[config].get('type'), origin=origin) else: raise AnsibleOptionsError( 'Invalid type for configuration option %s (from %s): %s' % (to_native( _get_entry(plugin_type, plugin_name, config)).strip(), origin, to_native(e))) # deal with restricted values if value is not None and 'choices' in defs[config] and defs[ config]['choices'] is not None: invalid_choices = True # assume the worst! if defs[config].get('type') == 'list': # for a list type, compare all values in type are allowed invalid_choices = not all(choice in defs[config]['choices'] for choice in value) else: # these should be only the simple data types (string, int, bool, float, etc) .. ignore dicts for now invalid_choices = value not in defs[config]['choices'] if invalid_choices: if isinstance(defs[config]['choices'], Mapping): valid = ', '.join([ to_text(k) for k in defs[config]['choices'].keys() ]) elif isinstance(defs[config]['choices'], string_types): valid = defs[config]['choices'] elif isinstance(defs[config]['choices'], Sequence): valid = ', '.join( [to_text(c) for c in defs[config]['choices']]) else: valid = defs[config]['choices'] raise AnsibleOptionsError( 'Invalid value "%s" for configuration option "%s", valid values are: %s' % (value, to_native(_get_entry(plugin_type, plugin_name, config)), valid)) # deal with deprecation of the setting if 'deprecated' in defs[config] and origin != 'default': self.DEPRECATED.append( (config, defs[config].get('deprecated'))) else: raise AnsibleError( 'Requested entry (%s) was not defined in configuration.' % to_native(_get_entry(plugin_type, plugin_name, config))) return value, origin
def native_eval(cls, msg, resource): msg = "{{ %s }}" % msg j2 = NativeEnvironment(loader=BaseLoader, undefined=StrictUndefined).from_string(msg) context = cls._get_context(resource) return j2.render(context)