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
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
 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)