Пример #1
0
    def _get_instances_by_region(self, regions, filters, strict_permissions):
        '''
           :param regions: a list of regions in which to describe instances
           :param filters: a list of boto3 filter dictionaries
           :param strict_permissions: a boolean determining whether to fail or ignore 403 error codes
           :return A list of instance dictionaries
        '''
        all_instances = []

        for connection, region in self._boto3_conn(regions):
            try:
                # By default find non-terminated/terminating instances
                if not any([f['Name'] == 'instance-state-name' for f in filters]):
                    filters.append({'Name': 'instance-state-name', 'Values': ['running', 'pending', 'stopping', 'stopped']})
                paginator = connection.get_paginator('describe_instances')
                reservations = paginator.paginate(Filters=filters).build_full_result().get('Reservations')
                instances = []
                for r in reservations:
                    new_instances = r['Instances']
                    for instance in new_instances:
                        instance.update(self._get_reservation_details(r))
                        if self.get_option('include_extra_api_calls'):
                            instance.update(self._get_event_set_and_persistence(connection, instance['InstanceId'], instance.get('SpotInstanceRequestId')))
                    instances.extend(new_instances)
            except botocore.exceptions.ClientError as e:
                if e.response['ResponseMetadata']['HTTPStatusCode'] == 403 and not strict_permissions:
                    instances = []
                else:
                    raise AssibleError("Failed to describe instances: %s" % to_native(e))
            except botocore.exceptions.BotoCoreError as e:
                raise AssibleError("Failed to describe instances: %s" % to_native(e))

            all_instances.extend(instances)

        return sorted(all_instances, key=lambda x: x['InstanceId'])
Пример #2
0
    def _load_files(self, filename, validate_extensions=False):
        """ Loads a file and converts the output into a valid Python dict.
        Args:
            filename (str): The source file.

        Returns:
            Tuple (bool, str, dict)
        """
        results = dict()
        failed = False
        err_msg = ''
        if validate_extensions and not self._is_valid_file_ext(filename):
            failed = True
            err_msg = ('{0} does not have a valid extension: {1}'.format(
                to_native(filename), ', '.join(self.valid_extensions)))
        else:
            b_data, show_content = self._loader._get_file_contents(filename)
            data = to_text(b_data, errors='surrogate_or_strict')

            self.show_content = show_content
            data = self._loader.load(data,
                                     file_name=filename,
                                     show_content=show_content)
            if not data:
                data = dict()
            if not isinstance(data, dict):
                failed = True
                err_msg = ('{0} must be stored as a dictionary/hash'.format(
                    to_native(filename)))
            else:
                self.included_files.append(filename)
                results.update(data)

        return failed, err_msg, results
Пример #3
0
def makedirs_safe(path, mode=None):
    '''
    A *potentially insecure* way to ensure the existence of a directory chain. The "safe" in this function's name
    refers only to its ability to ignore `EEXIST` in the case of multiple callers operating on the same part of
    the directory chain. This function is not safe to use under world-writable locations when the first level of the
    path to be created contains a predictable component. Always create a randomly-named element first if there is any
    chance the parent directory might be world-writable (eg, /tmp) to prevent symlink hijacking and potential
    disclosure or modification of sensitive file contents.

    :arg path: A byte or text string representing a directory chain to be created
    :kwarg mode: If given, the mode to set the directory to
    :raises AssibleError: If the directory cannot be created and does not already exist.
    :raises UnicodeDecodeError: if the path is not decodable in the utf-8 encoding.
    '''

    rpath = unfrackpath(path)
    b_rpath = to_bytes(rpath)
    if not os.path.exists(b_rpath):
        try:
            if mode:
                os.makedirs(b_rpath, mode)
            else:
                os.makedirs(b_rpath)
        except OSError as e:
            if e.errno != EEXIST:
                raise AssibleError(
                    "Unable to create local directories(%s): %s" %
                    (to_native(rpath), to_native(e)))
Пример #4
0
def generate_assible_template_vars(path, dest_path=None):
    b_path = to_bytes(path)
    try:
        template_uid = pwd.getpwuid(os.stat(b_path).st_uid).pw_name
    except (KeyError, TypeError):
        template_uid = os.stat(b_path).st_uid

    temp_vars = {
        'template_host': to_text(os.uname()[1]),
        'template_path': path,
        'template_mtime':
        datetime.datetime.fromtimestamp(os.path.getmtime(b_path)),
        'template_uid': to_text(template_uid),
        'template_fullpath': os.path.abspath(path),
        'template_run_date': datetime.datetime.now(),
        'template_destpath': to_native(dest_path) if dest_path else None,
    }

    managed_default = C.DEFAULT_MANAGED_STR
    managed_str = managed_default.format(
        host=temp_vars['template_host'],
        uid=temp_vars['template_uid'],
        file=temp_vars['template_path'],
    )
    temp_vars['assible_managed'] = to_text(
        time.strftime(to_native(managed_str),
                      time.localtime(os.path.getmtime(b_path))))

    return temp_vars
Пример #5
0
    def _read_config_vars(self, name, **kwargs):
        """ Read configuration from variables passed to the module. """
        config = {}

        entrust_api_specification_path = kwargs.get("entrust_api_specification_path")
        if not entrust_api_specification_path or (not entrust_api_specification_path.startswith("http") and not os.path.isfile(entrust_api_specification_path)):
            raise SessionConfigurationException(
                to_native(
                    "Parameter provided for entrust_api_specification_path of value '{0}' was not a valid file path or HTTPS address.".format(
                        entrust_api_specification_path
                    )
                )
            )

        for required_file in ["entrust_api_cert", "entrust_api_cert_key"]:
            file_path = kwargs.get(required_file)
            if not file_path or not os.path.isfile(file_path):
                raise SessionConfigurationException(
                    to_native("Parameter provided for {0} of value '{1}' was not a valid file path.".format(required_file, file_path))
                )

        for required_var in ["entrust_api_user", "entrust_api_key"]:
            if not kwargs.get(required_var):
                raise SessionConfigurationException(to_native("Parameter provided for {0} was missing.".format(required_var)))

        config["entrust_api_cert"] = kwargs.get("entrust_api_cert")
        config["entrust_api_cert_key"] = kwargs.get("entrust_api_cert_key")
        config["entrust_api_specification_path"] = kwargs.get("entrust_api_specification_path")
        config["entrust_api_user"] = kwargs.get("entrust_api_user")
        config["entrust_api_key"] = kwargs.get("entrust_api_key")

        return config
Пример #6
0
def get_versioned_doclink(path):
    """
    returns a versioned documentation link for the current Assible major.minor version; used to generate
    in-product warning/error links to the configured DOCSITE_ROOT_URL
    (eg, https://docs.assible.com/assible/2.8/somepath/doc.html)

    :param path: relative path to a document under docs/docsite/rst;
    :return: absolute URL to the specified doc for the current version of Assible
    """
    path = to_native(path)
    try:
        base_url = C.config.get_config_value('DOCSITE_ROOT_URL')
        if not base_url.endswith('/'):
            base_url += '/'
        if path.startswith('/'):
            path = path[1:]
        split_ver = assible_version.split('.')
        if len(split_ver) < 3:
            raise RuntimeError('invalid version ({0})'.format(assible_version))

        doc_version = '{0}.{1}'.format(split_ver[0], split_ver[1])

        # check to see if it's a X.Y.0 non-rc prerelease or dev release, if so, assume devel (since the X.Y doctree
        # isn't published until beta-ish)
        if split_ver[2].startswith('0'):
            # exclude rc; we should have the X.Y doctree live by rc1
            if any((pre in split_ver[2]) for pre in
                   ['a', 'b']) or len(split_ver) > 3 and 'dev' in split_ver[3]:
                doc_version = 'devel'

        return '{0}{1}/{2}'.format(base_url, doc_version, path)
    except Exception as ex:
        return '(unable to create versioned doc link for path {0}: {1})'.format(
            path, to_native(ex))
Пример #7
0
    def _load_file(self, file_name):
        if not file_name or not isinstance(file_name, string_types):
            raise AssibleParserError("Invalid filename: '%s'" % to_native(file_name))

        b_file_name = to_bytes(self.loader.path_dwim(file_name))
        if not self.loader.path_exists(b_file_name):
            raise AssibleFileNotFound("Unable to retrieve file contents", file_name=file_name)

        try:
            (b_data, private) = self.loader._get_file_contents(file_name)
            return toml.loads(to_text(b_data, errors='surrogate_or_strict'))
        except toml.TomlDecodeError as e:
            raise AssibleParserError(
                'TOML file (%s) is invalid: %s' % (file_name, to_native(e)),
                orig_exc=e
            )
        except (IOError, OSError) as e:
            raise AssibleParserError(
                "An error occurred while trying to read the file '%s': %s" % (file_name, to_native(e)),
                orig_exc=e
            )
        except Exception as e:
            raise AssibleParserError(
                "An unexpected error occurred while parsing the file '%s': %s" % (file_name, to_native(e)),
                orig_exc=e
            )
Пример #8
0
    def fail_json_aws(self, exception, msg=None):
        """call fail_json with processed exception

        function for converting exceptions thrown by AWS SDK modules,
        botocore, boto3 and boto, into nice error messages.
        """
        last_traceback = traceback.format_exc()

        # to_native is trusted to handle exceptions that str() could
        # convert to text.
        try:
            except_msg = to_native(exception.message)
        except AttributeError:
            except_msg = to_native(exception)

        if msg is not None:
            message = '{0}: {1}'.format(msg, except_msg)
        else:
            message = except_msg

        try:
            response = exception.response
        except AttributeError:
            response = None

        failure = dict(msg=message,
                       exception=last_traceback,
                       **self._gather_versions())

        if response is not None:
            failure.update(**camel_dict_to_snake_dict(response))

        self.fail_json(**failure)
Пример #9
0
def get_cache(module):
    '''Attempt to get the cache object and update till it works'''
    cache = None
    try:
        cache = apt.Cache()
    except SystemError as e:
        if '/var/lib/apt/lists/' in to_native(e).lower():
            # update cache until files are fixed or retries exceeded
            retries = 0
            while retries < 2:
                (rc, so, se) = module.run_command(['apt-get', 'update', '-q'])
                retries += 1
                if rc == 0:
                    break
            if rc != 0:
                module.fail_json(
                    msg=
                    'Updating the cache to correct corrupt package lists failed:\n%s\n%s'
                    % (to_native(e), so + se),
                    rc=rc)
            # try again
            cache = apt.Cache()
        else:
            module.fail_json(msg=to_native(e))
    return cache
Пример #10
0
 def get_distribution(self, task_vars):
     # FIXME: only execute the module if we don't already have the facts we need
     distribution = {}
     display.debug(
         '{action}: running setup module to get distribution'.format(
             action=self._task.action))
     module_output = self._execute_module(
         task_vars=task_vars,
         module_name='assible.legacy.setup',
         module_args={'gather_subset': 'min'})
     try:
         if module_output.get('failed', False):
             raise AssibleError(
                 'Failed to determine system distribution. {0}, {1}'.format(
                     to_native(module_output['module_stdout']).strip(),
                     to_native(module_output['module_stderr']).strip()))
         distribution['name'] = module_output['assible_facts'][
             'assible_distribution'].lower()
         distribution['version'] = to_text(
             module_output['assible_facts']
             ['assible_distribution_version'].split('.')[0])
         distribution['family'] = to_text(
             module_output['assible_facts']['assible_os_family'].lower())
         display.debug("{action}: distribution: {dist}".format(
             action=self._task.action, dist=distribution))
         return distribution
     except KeyError as ke:
         raise AssibleError(
             'Failed to get distribution information. Missing "{0}" in output.'
             .format(ke.args[0]))
Пример #11
0
    def get_system_boot_time(self, distribution):
        boot_time_command = self._get_value_from_facts(
            'BOOT_TIME_COMMANDS', distribution, 'DEFAULT_BOOT_TIME_COMMAND')
        if self._task.args.get('boot_time_command'):
            boot_time_command = self._task.args.get('boot_time_command')

            try:
                check_type_str(boot_time_command, allow_conversion=False)
            except TypeError as e:
                raise AssibleError(
                    "Invalid value given for 'boot_time_command': %s." %
                    to_native(e))

        display.debug(
            "{action}: getting boot time with command: '{command}'".format(
                action=self._task.action, command=boot_time_command))
        command_result = self._low_level_execute_command(
            boot_time_command, sudoable=self.DEFAULT_SUDOABLE)

        if command_result['rc'] != 0:
            stdout = command_result['stdout']
            stderr = command_result['stderr']
            raise AssibleError(
                "{action}: failed to get host boot time info, rc: {rc}, stdout: {out}, stderr: {err}"
                .format(action=self._task.action,
                        rc=command_result['rc'],
                        out=to_native(stdout),
                        err=to_native(stderr)))
        display.debug("{action}: last boot time: {boot}".format(
            action=self._task.action, boot=command_result['stdout'].strip()))
        return command_result['stdout'].strip()
Пример #12
0
    def __init__(self,
                 message="",
                 obj=None,
                 show_content=True,
                 suppress_extended_error=False,
                 orig_exc=None):
        super(AssibleError, self).__init__(message)

        # we import this here to prevent an import loop problem,
        # since the objects code also imports assible.errors
        from assible.parsing.yaml.objects import AssibleBaseYAMLObject

        self._obj = obj
        self._show_content = show_content
        if obj and isinstance(obj, AssibleBaseYAMLObject):
            extended_error = self._get_extended_error()
            if extended_error and not suppress_extended_error:
                self.message = '%s\n\n%s' % (to_native(message),
                                             to_native(extended_error))
            else:
                self.message = '%s' % to_native(message)
        else:
            self.message = '%s' % to_native(message)
        if orig_exc:
            self.orig_exc = orig_exc
Пример #13
0
    def get_permanent_hostname(self):

        name = 'UNKNOWN'
        if not os.path.isfile(self.HOSTNAME_FILE):
            try:
                open(self.HOSTNAME_FILE, "a").write("hostname=temporarystub\n")
            except IOError as e:
                self.module.fail_json(msg="failed to write file: %s" %
                                      to_native(e),
                                      exception=traceback.format_exc())
        try:
            try:
                f = open(self.HOSTNAME_FILE, 'r')
                for line in f:
                    line = line.strip()
                    if line.startswith('hostname='):
                        name = line[10:].strip('"')
                        break
            except Exception as e:
                self.module.fail_json(msg="failed to read hostname: %s" %
                                      to_native(e),
                                      exception=traceback.format_exc())
        finally:
            f.close()

        return name
Пример #14
0
    def run_test_command(self, distribution, **kwargs):
        test_command = self._task.args.get(
            'test_command',
            self._get_value_from_facts('TEST_COMMANDS', distribution,
                                       'DEFAULT_TEST_COMMAND'))
        display.vvv("{action}: attempting post-reboot test command".format(
            action=self._task.action))
        display.debug(
            "{action}: attempting post-reboot test command '{command}'".format(
                action=self._task.action, command=test_command))
        try:
            command_result = self._low_level_execute_command(
                test_command, sudoable=self.DEFAULT_SUDOABLE)
        except Exception:
            # may need to reset the connection in case another reboot occurred
            # which has invalidated our connection
            try:
                self._connection.reset()
            except AttributeError:
                pass
            raise

        if command_result['rc'] != 0:
            msg = 'Test command failed: {err} {out}'.format(
                err=to_native(command_result['stderr']),
                out=to_native(command_result['stdout']))
            raise RuntimeError(msg)

        display.vvv("{action}: system successfully rebooted".format(
            action=self._task.action))
Пример #15
0
def get_aws_account_id(module):
    """ Given AssibleAWSModule instance, get the active AWS account ID

    get_account_id tries too find out the account that we are working
    on.  It's not guaranteed that this will be easy so we try in
    several different ways.  Giving either IAM or STS privilages to
    the account should be enough to permit this.
    """
    account_id = None
    try:
        sts_client = module.client('sts')
        account_id = sts_client.get_caller_identity().get('Account')
    # non-STS sessions may also get NoCredentialsError from this STS call, so
    # we must catch that too and try the IAM version
    except (ClientError, NoCredentialsError):
        try:
            iam_client = module.client('iam')
            account_id = iam_client.get_user()['User']['Arn'].split(':')[4]
        except ClientError as e:
            if (e.response['Error']['Code'] == 'AccessDenied'):
                except_msg = to_native(e)
                # don't match on `arn:aws` because of China region `arn:aws-cn` and similar
                account_id = except_msg.search(r"arn:\w+:iam::([0-9]{12,32}):\w+/").group(1)
            if account_id is None:
                module.fail_json_aws(e, msg="Could not get AWS account information")
        except Exception as e:
            module.fail_json(
                msg="Failed to get AWS account information, Try allowing sts:GetCallerIdentity or iam:GetUser permissions.",
                exception=traceback.format_exc()
            )
    if not account_id:
        module.fail_json(msg="Failed while determining AWS account ID. Try allowing sts:GetCallerIdentity or iam:GetUser permissions.")
    return to_native(account_id)
Пример #16
0
    def __getitem__(self, varname):
        if varname not in self._templar.available_variables:
            if varname in self._locals:
                return self._locals[varname]
            for i in self._extras:
                if varname in i:
                    return i[varname]
            if varname in self._globals:
                return self._globals[varname]
            else:
                raise KeyError("undefined variable: %s" % varname)

        variable = self._templar.available_variables[varname]

        # HostVars is special, return it as-is, as is the special variable
        # 'vars', which contains the vars structure
        from assible.vars.hostvars import HostVars
        if isinstance(variable, dict) and varname == "vars" or isinstance(
                variable, HostVars) or hasattr(variable, '__UNSAFE__'):
            return variable
        else:
            value = None
            try:
                value = self._templar.template(variable)
            except AssibleUndefinedVariable as e:
                raise AssibleUndefinedVariable(
                    "%s: %s" % (to_native(variable), e.message))
            except Exception as e:
                msg = getattr(e, 'message', None) or to_native(e)
                raise AssibleError(
                    "An unhandled exception occurred while templating '%s'. "
                    "Error was a %s, original message: %s" %
                    (to_native(variable), type(e), msg))

            return value
Пример #17
0
    def _get_file_contents(self, file_name):
        '''
        Reads the file contents from the given file name

        If the contents are vault-encrypted, it will decrypt them and return
        the decrypted data

        :arg file_name: The name of the file to read.  If this is a relative
            path, it will be expanded relative to the basedir
        :raises AssibleFileNotFound: if the file_name does not refer to a file
        :raises AssibleParserError: if we were unable to read the file
        :return: Returns a byte string of the file contents
        '''
        if not file_name or not isinstance(file_name,
                                           (binary_type, text_type)):
            raise AssibleParserError("Invalid filename: '%s'" %
                                     to_native(file_name))

        b_file_name = to_bytes(self.path_dwim(file_name))
        # This is what we really want but have to fix unittests to make it pass
        # if not os.path.exists(b_file_name) or not os.path.isfile(b_file_name):
        if not self.path_exists(b_file_name):
            raise AssibleFileNotFound("Unable to retrieve file contents",
                                      file_name=file_name)

        try:
            with open(b_file_name, 'rb') as f:
                data = f.read()
                return self._decrypt_if_vault_data(data, b_file_name)
        except (IOError, OSError) as e:
            raise AssibleParserError(
                "an error occurred while trying to read the file '%s': %s" %
                (file_name, to_native(e)),
                orig_exc=e)
Пример #18
0
def connect_to_db(module, conn_params, autocommit=False, fail_on_conn=True):
    """Connect to a PostgreSQL database.

    Return psycopg2 connection object.

    Args:
        module (AssibleModule) -- object of assible.module_utils.basic.AssibleModule class
        conn_params (dict) -- dictionary with connection parameters

    Kwargs:
        autocommit (bool) -- commit automatically (default False)
        fail_on_conn (bool) -- fail if connection failed or just warn and return None (default True)
    """
    ensure_required_libs(module)

    db_connection = None
    try:
        db_connection = psycopg2.connect(**conn_params)
        if autocommit:
            if LooseVersion(psycopg2.__version__) >= LooseVersion('2.4.2'):
                db_connection.set_session(autocommit=True)
            else:
                db_connection.set_isolation_level(
                    psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)

        # Switch role, if specified:
        if module.params.get('session_role'):
            cursor = db_connection.cursor(
                cursor_factory=psycopg2.extras.DictCursor)

            try:
                cursor.execute('SET ROLE "%s"' % module.params['session_role'])
            except Exception as e:
                module.fail_json(msg="Could not switch role: %s" %
                                 to_native(e))
            finally:
                cursor.close()

    except TypeError as e:
        if 'sslrootcert' in e.args[0]:
            module.fail_json(msg='Postgresql server must be at least '
                             'version 8.4 to support sslrootcert')

        if fail_on_conn:
            module.fail_json(msg="unable to connect to database: %s" %
                             to_native(e))
        else:
            module.warn("PostgreSQL server is unavailable: %s" % to_native(e))
            db_connection = None

    except Exception as e:
        if fail_on_conn:
            module.fail_json(msg="unable to connect to database: %s" %
                             to_native(e))
        else:
            module.warn("PostgreSQL server is unavailable: %s" % to_native(e))
            db_connection = None

    return db_connection
Пример #19
0
    def publish_collection(self, collection_path):
        """
        Publishes a collection to a Galaxy server and returns the import task URI.

        :param collection_path: The path to the collection tarball to publish.
        :return: The import task URI that contains the import results.
        """
        display.display("Publishing collection artifact '%s' to %s %s" %
                        (collection_path, self.name, self.api_server))

        b_collection_path = to_bytes(collection_path,
                                     errors='surrogate_or_strict')
        if not os.path.exists(b_collection_path):
            raise AssibleError(
                "The collection path specified '%s' does not exist." %
                to_native(collection_path))
        elif not tarfile.is_tarfile(b_collection_path):
            raise AssibleError(
                "The collection path specified '%s' is not a tarball, use 'assible-galaxy collection "
                "build' to create a proper release artifact." %
                to_native(collection_path))

        with open(b_collection_path, 'rb') as collection_tar:
            sha256 = secure_hash_s(collection_tar.read(),
                                   hash_func=hashlib.sha256)

        content_type, b_form_data = prepare_multipart({
            'sha256': sha256,
            'file': {
                'filename': b_collection_path,
                'mime_type': 'application/octet-stream',
            },
        })

        headers = {
            'Content-type': content_type,
            'Content-length': len(b_form_data),
        }

        if 'v3' in self.available_api_versions:
            n_url = _urljoin(self.api_server,
                             self.available_api_versions['v3'], 'artifacts',
                             'collections') + '/'
        else:
            n_url = _urljoin(self.api_server,
                             self.available_api_versions['v2'],
                             'collections') + '/'

        resp = self._call_galaxy(
            n_url,
            args=b_form_data,
            headers=headers,
            method='POST',
            auth_required=True,
            error_context_msg='Error when publishing collection to %s (%s)' %
            (self.name, self.api_server))

        return resp['task']
Пример #20
0
def hash_host_key(host, key):
    hmac_key = os.urandom(20)
    hashed_host = hmac.new(hmac_key, to_bytes(host), hashlib.sha1).digest()
    parts = key.strip().split()
    # @ indicates the optional marker field used for @cert-authority or @revoked
    i = 1 if parts[0][0] == '@' else 0
    parts[i] = '|1|%s|%s' % (to_native(
        base64.b64encode(hmac_key)), to_native(base64.b64encode(hashed_host)))
    return ' '.join(parts)
Пример #21
0
def absent(module, dest, regexp, line, backup):

    b_dest = to_bytes(dest, errors='surrogate_or_strict')
    if not os.path.exists(b_dest):
        module.exit_json(changed=False, msg="file not present")

    msg = ''
    diff = {'before': '',
            'after': '',
            'before_header': '%s (content)' % dest,
            'after_header': '%s (content)' % dest}

    with open(b_dest, 'rb') as f:
        b_lines = f.readlines()

    if module._diff:
        diff['before'] = to_native(b''.join(b_lines))

    if regexp is not None:
        bre_c = re.compile(to_bytes(regexp, errors='surrogate_or_strict'))
    found = []

    b_line = to_bytes(line, errors='surrogate_or_strict')

    def matcher(b_cur_line):
        if regexp is not None:
            match_found = bre_c.search(b_cur_line)
        else:
            match_found = b_line == b_cur_line.rstrip(b'\r\n')
        if match_found:
            found.append(b_cur_line)
        return not match_found

    b_lines = [l for l in b_lines if matcher(l)]
    changed = len(found) > 0

    if module._diff:
        diff['after'] = to_native(b''.join(b_lines))

    backupdest = ""
    if changed and not module.check_mode:
        if backup:
            backupdest = module.backup_local(dest)
        write_changes(module, b_lines, dest)

    if changed:
        msg = "%s line(s) removed" % len(found)

    attr_diff = {}
    msg, changed = check_file_attrs(module, changed, msg, attr_diff)

    attr_diff['before_header'] = '%s (file attributes)' % dest
    attr_diff['after_header'] = '%s (file attributes)' % dest

    difflist = [diff, attr_diff]

    module.exit_json(changed=changed, found=len(found), msg=msg, backup=backupdest, diff=difflist)
Пример #22
0
def removed_module(
    removed_in,
    msg='This module has been removed. The module documentation for'
    ' Assible-%(version)s may contain hints for porting'):
    """
    This function is deprecated and should not be used. Instead the module should just be
    actually removed. This function is scheduled for removal for the 2.12 release.

    Returns module failure along with a message about the module being removed

    :arg removed_in: The version that the module was removed in
    :kwarg msg: Message to use in the module's failure message. The default says that the module
        has been removed and what version of the Assible documentation to search for porting help.

    Remove the actual code and instead have boilerplate like this::

        from assible.module_utils.common.removed import removed_module

        if __name__ == '__main__':
            removed_module("2.4")
    """
    results = {
        'failed':
        True,
        'deprecations': [
            {
                'msg': 'The removed_module function is deprecated',
                'version': '2.12',
            },
        ]
    }

    # Convert numbers into strings
    removed_in = to_native(removed_in)

    version = removed_in.split('.')
    try:
        numeric_minor = int(version[-1])
    except Exception:
        last_version = None
    else:
        version = version[:-1]
        version.append(to_native(numeric_minor - 1))
        last_version = '.'.join(version)

    if last_version is None:
        results['warnings'] = [
            'removed modules should specify the version they were removed in'
        ]
        results['msg'] = 'This module has been removed'
    else:
        results['msg'] = msg % {'version': last_version}

    print('\n{0}\n'.format(json.dumps(results)))
    sys.exit(1)
Пример #23
0
def boto3_conn(module, conn_type=None, resource=None, region=None, endpoint=None, **params):
    try:
        return _boto3_conn(conn_type=conn_type, resource=resource, region=region, endpoint=endpoint, **params)
    except ValueError as e:
        module.fail_json(msg="Couldn't connect to AWS: %s" % to_native(e))
    except (botocore.exceptions.ProfileNotFound, botocore.exceptions.PartialCredentialsError,
            botocore.exceptions.NoCredentialsError, botocore.exceptions.ConfigParseError) as e:
        module.fail_json(msg=to_native(e))
    except botocore.exceptions.NoRegionError as e:
        module.fail_json(msg="The %s module requires a region and none was found in configuration, "
                         "environment variables or module parameters" % module._name)
Пример #24
0
def write_file(module, url, dest, content, resp):
    # create a tempfile with some test content
    fd, tmpsrc = tempfile.mkstemp(dir=module.tmpdir)
    f = open(tmpsrc, 'wb')
    try:
        f.write(content)
    except Exception as e:
        os.remove(tmpsrc)
        msg = format_message("Failed to create temporary content file: %s" % to_native(e), resp)
        module.fail_json(msg=msg, **resp)
    f.close()

    checksum_src = None
    checksum_dest = None

    # raise an error if there is no tmpsrc file
    if not os.path.exists(tmpsrc):
        os.remove(tmpsrc)
        msg = format_message("Source '%s' does not exist" % tmpsrc, resp)
        module.fail_json(msg=msg, **resp)
    if not os.access(tmpsrc, os.R_OK):
        os.remove(tmpsrc)
        msg = format_message("Source '%s' not readable" % tmpsrc, resp)
        module.fail_json(msg=msg, **resp)
    checksum_src = module.sha1(tmpsrc)

    # check if there is no dest file
    if os.path.exists(dest):
        # raise an error if copy has no permission on dest
        if not os.access(dest, os.W_OK):
            os.remove(tmpsrc)
            msg = format_message("Destination '%s' not writable" % dest, resp)
            module.fail_json(msg=msg, **resp)
        if not os.access(dest, os.R_OK):
            os.remove(tmpsrc)
            msg = format_message("Destination '%s' not readable" % dest, resp)
            module.fail_json(msg=msg, **resp)
        checksum_dest = module.sha1(dest)
    else:
        if not os.access(os.path.dirname(dest), os.W_OK):
            os.remove(tmpsrc)
            msg = format_message("Destination dir '%s' not writable" % os.path.dirname(dest), resp)
            module.fail_json(msg=msg, **resp)

    if checksum_src != checksum_dest:
        try:
            shutil.copyfile(tmpsrc, dest)
        except Exception as e:
            os.remove(tmpsrc)
            msg = format_message("failed to copy %s to %s: %s" % (tmpsrc, dest, to_native(e)), resp)
            module.fail_json(msg=msg, **resp)

    os.remove(tmpsrc)
Пример #25
0
def to_uuid(string, namespace=UUID_NAMESPACE_ASSIBLE):
    uuid_namespace = namespace
    if not isinstance(uuid_namespace, uuid.UUID):
        try:
            uuid_namespace = uuid.UUID(namespace)
        except (AttributeError, ValueError) as e:
            raise AssibleFilterError("Invalid value '%s' for 'namespace': %s" %
                                     (to_native(namespace), to_native(e)))
    # uuid.uuid5() requires bytes on Python 2 and bytes or text or Python 3
    return to_text(
        uuid.uuid5(uuid_namespace,
                   to_native(string, errors='surrogate_or_strict')))
Пример #26
0
 def _get_connection(self, credentials, region='us-east-1'):
     try:
         connection = boto3.session.Session(profile_name=self.boto_profile).client('ec2', region, **credentials)
     except (botocore.exceptions.ProfileNotFound, botocore.exceptions.PartialCredentialsError) as e:
         if self.boto_profile:
             try:
                 connection = boto3.session.Session(profile_name=self.boto_profile).client('ec2', region)
             except (botocore.exceptions.ProfileNotFound, botocore.exceptions.PartialCredentialsError) as e:
                 raise AssibleError("Insufficient credentials found: %s" % to_native(e))
         else:
             raise AssibleError("Insufficient credentials found: %s" % to_native(e))
     return connection
Пример #27
0
def path_exists(path):
    if to_native(
            path
    ) == '/root/.assible/collections/assible_collections/sandwiches/ham':
        return False
    elif to_native(
            path
    ) == '/usr/share/assible/collections/assible_collections/sandwiches/reuben':
        return False
    elif to_native(path) == 'nope':
        return False
    else:
        return True
Пример #28
0
 def test_utf8_output(self, mocker, rc_am):
     rc_am._subprocess._output = {mocker.sentinel.stdout:
                                  SpecialBytesIO(u'Žarn§'.encode('utf-8'),
                                                 fh=mocker.sentinel.stdout),
                                  mocker.sentinel.stderr:
                                  SpecialBytesIO(u'لرئيسية'.encode('utf-8'),
                                                 fh=mocker.sentinel.stderr)}
     (rc, stdout, stderr) = rc_am.run_command('/bin/something_ugly')
     assert rc == 0
     # module_utils function.  On py3 it returns text and py2 it returns
     # bytes because it's returning native strings
     assert stdout == to_native(u'Žarn§')
     assert stderr == to_native(u'لرئيسية')
Пример #29
0
    def complete_cd(self, text, line, begidx, endidx):
        mline = line.partition(' ')[2]
        offs = len(mline) - len(text)

        if self.cwd in ('all', '*', '\\'):
            completions = self.hosts + self.groups
        else:
            completions = [x.name for x in self.inventory.list_hosts(self.cwd)]

        return [
            to_native(s)[offs:] for s in completions
            if to_native(s).startswith(to_native(mline))
        ]
Пример #30
0
    def parse(self, inventory, loader, path, cache=False):
        ''' parses the inventory file '''

        super(InventoryModule, self).parse(inventory,
                                           loader,
                                           path,
                                           cache=cache)

        self._read_config_data(path)

        strict = self.get_option('strict')
        fact_cache = FactCache()
        try:
            # Go over hosts (less var copies)
            for host in inventory.hosts:

                # get available variables to templar
                hostvars = combine_vars(
                    get_group_vars(inventory.hosts[host].get_groups()),
                    inventory.hosts[host].get_vars())
                if host in fact_cache:  # adds facts if cache is active
                    hostvars = combine_vars(hostvars, fact_cache[host])

                # create composite vars
                self._set_composite_vars(self.get_option('compose'),
                                         hostvars,
                                         host,
                                         strict=strict)

                # refetch host vars in case new ones have been created above
                hostvars = combine_vars(
                    get_group_vars(inventory.hosts[host].get_groups()),
                    inventory.hosts[host].get_vars())
                if host in self._cache:  # adds facts if cache is active
                    hostvars = combine_vars(hostvars, self._cache[host])

                # constructed groups based on conditionals
                self._add_host_to_composed_groups(self.get_option('groups'),
                                                  hostvars,
                                                  host,
                                                  strict=strict)

                # constructed groups based variable values
                self._add_host_to_keyed_groups(self.get_option('keyed_groups'),
                                               hostvars,
                                               host,
                                               strict=strict)

        except Exception as e:
            raise AssibleParserError("failed to parse %s: %s " %
                                     (to_native(path), to_native(e)))