Exemplo n.º 1
0
    def execute_remove(self):
        """
        Remove a list of repository from the local system.
        """

        if len(self.args) == 0:
            raise cli_exceptions.CliOptionsError(
                '- you must specify at least one role to remove.')

        galaxy_context = self._get_galaxy_context(self.options, self.config)

        if self.args:
            match_filter = matchers.MatchLabels(self.args)

        return remove.remove(galaxy_context,
                             repository_match_filter=match_filter,
                             display_callback=self.display)
Exemplo n.º 2
0
    def execute_info(self):
        """
        Display detailed information about an installed collection, as well as info available from the Galaxy API.
        """

        if len(self.args) == 0:
            # the user needs to specify a collection
            raise cli_exceptions.CliOptionsError("- you must specify a collection name")

        log.debug('args=%s', self.args)

        galaxy_context = self._get_galaxy_context(self.options, self.config)

        repository_spec_strings = self.args

        api = rest_api.GalaxyAPI(galaxy_context)

        # FIXME: rc?
        return info.info_repository_specs(galaxy_context, api, repository_spec_strings,
                                          display_callback=self.display,
                                          offline=self.options.offline)
Exemplo n.º 3
0
    def parse(self):
        ''' create an options parser for bin/ansible '''

        self.parser = cli.CLI.base_parser(
            usage="usage: %%prog [%s] [--help] [options] ..." % "|".join(self.VALID_ACTIONS),
            epilog="\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0])
        )

        # common
        self.parser.add_option('-s', '--server', dest='server_url', default=None, help='The API server destination')

        self.parser.add_option('-c', '--ignore-certs', action='store_true', dest='ignore_certs', default=None,
                               help='Ignore SSL certificate validation errors.')
        self.parser.add_option('--config', dest='cli_config_file', default=None,
                               help='path to a mazer config file (default: %s)' % defaults.DEFAULT_CONFIG_FILE)
        self.set_action()

        super(GalaxyCLI, self).parse()

        if self.action == 'install' and getattr(self.options, 'collections_path') and getattr(self.options, 'global_install'):
            raise cli_exceptions.CliOptionsError('--content-path and --global are mutually exclusive')
Exemplo n.º 4
0
    def execute_remove(self):
        """
        removes the list of roles passed as arguments from the local system.
        """

        if len(self.args) == 0:
            raise cli_exceptions.CliOptionsError(
                '- you must specify at least one role to remove.')

        for role_name in self.args:
            role = GalaxyContent(self.galaxy, role_name)
            try:
                if role.remove():
                    self.display('- successfully removed %s' % role_name)
                else:
                    self.display('- %s is not installed, skipping.' %
                                 role_name)
            except Exception as e:
                raise cli_exceptions.GalaxyCliError(
                    "Failed to remove role %s: %s" % (role_name, str(e)))

        return 0
Exemplo n.º 5
0
    def set_action(self):
        """
        Get the action the user wants to execute from the sys argv list.
        """
        for i in range(0, len(self.args)):
            arg = self.args[i]
            if arg in self.VALID_ACTIONS:
                self.action = arg
                del self.args[i]
                break

        if not self.action:
            # if we're asked for help or version, we don't need an action.
            # have to use a special purpose Option Parser to figure that out as
            # the standard OptionParser throws an error for unknown options and
            # without knowing action, we only know of a subset of the options
            # that could be legal for this command
            tmp_parser = InvalidOptsParser(self.parser)
            tmp_options, tmp_args = tmp_parser.parse_args(self.args)
            if not (hasattr(tmp_options, 'help') and tmp_options.help) or (
                    hasattr(tmp_options, 'version') and tmp_options.version):
                raise cli_exceptions.CliOptionsError("Missing required action")
Exemplo n.º 6
0
Arquivo: galaxy.py Projeto: tima/mazer
    def execute_info(self):
        """
        Display detailed information about an installed collection, as well as info available from the Galaxy API.
        """

        if len(self.args) == 0:
            # the user needs to specify a role
            raise cli_exceptions.CliOptionsError(
                "- you must specify a user/role name")

        log.debug('args=%s', self.args)

        galaxy_context = self._get_galaxy_context(self.options, self.config)

        content_specs = self.args

        # FIXME: rc?
        return info.info_content_specs(galaxy_context,
                                       self.api,
                                       content_specs,
                                       display_callback=self.display,
                                       offline=self.options.offline)
Exemplo n.º 7
0
def test_cli_options_error():
    cli_options_error = cli_exceptions.CliOptionsError()

    assert isinstance(
        cli_options_error, Exception
    ), 'instance of CliOptionsError should be subclass of Exception'
Exemplo n.º 8
0
    def execute_install(self):
        """
        uses the args list of roles to be installed, unless -f was specified. The list of roles
        can be a name (which will be downloaded via the galaxy API and github), or it can be a local .tar.gz file.
        """
        role_file = self.options.role_file

        if len(self.args) == 0 and role_file is None:
            # the user needs to specify one of either --role-file or specify a single user/role name
            raise cli_exceptions.CliOptionsError(
                "- you must specify a user/role name or a roles file")

        no_deps = self.options.no_deps
        force = self.options.force

        roles_left = []
        if role_file:
            try:
                f = open(role_file, 'r')
                if role_file.endswith('.yaml') or role_file.endswith('.yml'):
                    try:
                        required_roles = yaml.safe_load(f.read())
                    except Exception as e:
                        raise cli_exceptions.GalaxyCliError(
                            "Unable to load data from the requirements file: %s"
                            % role_file)

                    if required_roles is None:
                        raise cli_exceptions.GalaxyCliError(
                            "No roles found in file: %s" % role_file)

                    for role in required_roles:
                        if "include" not in role:
                            role = GalaxyContent.yaml_parse(role)
                            log.info("found role %s in yaml file", str(role))
                            if "name" not in role and "scm" not in role:
                                raise cli_exceptions.GalaxyCliError(
                                    "Must specify name or src for role")
                            roles_left.append(
                                GalaxyContent(self.galaxy, **role))
                        else:
                            with open(role["include"]) as f_include:
                                try:
                                    roles_left += [
                                        GalaxyContent(self.galaxy, **r)
                                        for r in (
                                            GalaxyContent.yaml_parse(i)
                                            for i in yaml.safe_load(f_include))
                                    ]
                                except Exception as e:
                                    msg = "Unable to load data from the include requirements file: %s %s"
                                    raise cli_exceptions.GalaxyCliError(
                                        msg % (role_file, e))
                else:
                    log.warn(
                        "DEPRECATED going forward only the yaml format will be supported (version='%s')",
                        "2.6")
                    # roles listed in a file, one per line
                    for rline in f.readlines():
                        if rline.startswith("#") or rline.strip() == '':
                            continue
                        log.debug('found role %s in text file', str(rline))
                        role = GalaxyContent.yaml_parse(rline.strip())
                        roles_left.append(GalaxyContent(self.galaxy, **role))
                f.close()
            except (IOError, OSError) as e:
                raise cli_exceptions.GalaxyCliError('Unable to open %s: %s' %
                                                    (role_file, str(e)))
        else:
            # roles were specified directly, so we'll just go out grab them
            # (and their dependencies, unless the user doesn't want us to).
            for rname in self.args:
                role = GalaxyContent.yaml_parse(rname.strip())
                roles_left.append(GalaxyContent(self.galaxy, **role))

        for role in roles_left:
            # only process roles in roles files when names matches if given
            if role_file and self.args and role.name not in self.args:
                log.info('Skipping role %s', role.name)
                continue

            log.info('Processing role %s ', role.name)

            # query the galaxy API for the role data

            if role.install_info is not None:
                if role.install_info['version'] != role.version or force:
                    if force:
                        self.display(
                            '- changing role %s from %s to %s' % role.name,
                            role.install_info['version'], role.version
                            or "unspecified")
                        role.remove()
                    else:
                        log.warn(
                            '- %s (%s) is already installed - use --force to change version to %s',
                            role.name, role.install_info['version'],
                            role.version or "unspecified")
                        continue
                else:
                    if not force:
                        self.display('- %s is already installed, skipping.' %
                                     str(role))
                        continue

            try:
                installed = role.install()
            except exceptions.GalaxyError as e:
                self.log.exception(e)
                log.warn("- %s was NOT installed successfully: %s ", role.name,
                         str(e))
                self.exit_without_ignore()
                continue

            # install dependencies, if we want them
            if not no_deps and installed:
                if not role.metadata:
                    log.warn("Meta file %s is empty. Skipping dependencies.",
                             role.path)
                else:
                    role_dependencies = role.metadata.get('dependencies') or []
                    for dep in role_dependencies:
                        log.debug('Installing dep %s', dep)
                        dep_info = GalaxyContent.yaml_parse(dep)
                        dep_role = GalaxyContent(self.galaxy, **dep_info)
                        if '.' not in dep_role.name and '.' not in dep_role.src and dep_role.scm is None:
                            # we know we can skip this, as it's not going to
                            # be found on galaxy.ansible.com
                            continue
                        if dep_role.install_info is None:
                            if dep_role not in roles_left:
                                self.display('- adding dependency: %s' %
                                             str(dep_role))
                                roles_left.append(dep_role)
                            else:
                                self.display(
                                    '- dependency %s already pending installation.'
                                    % dep_role.name)
                        else:
                            if dep_role.install_info[
                                    'version'] != dep_role.version:
                                log.warning(
                                    '- dependency %s from role %s differs from already installed version (%s), skipping'
                                    % str(dep_role), role.name,
                                    dep_role.install_info['version'])
                            else:
                                self.display(
                                    '- dependency %s is already installed, skipping.'
                                    % dep_role.name)

            if not installed:
                log.warning("- %s was NOT installed successfully.", role.name)
                self.exit_without_ignore()

        return 0
Exemplo n.º 9
0
    def execute_content_install(self):
        """
        uses the args list of roles to be installed, unless -f was specified. The list of roles
        can be a name (which will be downloaded via the galaxy API and github), or it can be a local .tar.gz file.
        """

        # FIXME - still not sure where to put this or how best to handle it,
        #         but for now just detect when it's not provided and offer up
        #         default paths
        #
        # NOTE: kind of gaming the arg parsing here with self.options.content_path,
        #       and how CLI.unfrack_paths works. It's a bit of a hack... should
        #       probably find a better solution before this goes GA
        #
        # Fix content_path if this was not provided
        if self.options.content_type != "all" and self.options.content_type not in CONTENT_TYPES:
            raise cli_exceptions.CliOptionsError(
                "- invalid Galaxy Content type provided: %s\n  - Expected one of: %s"
                % (self.options.content_type, ", ".join(CONTENT_TYPES)))

        self.log.debug('galaxy.options: %s', self.galaxy.options)
        # If someone provides a --roles-path at the command line, we assume this is
        # for use with a legacy role and we want to maintain backwards compat
        if self.options.roles_path:
            self.log.warn(
                'Assuming content is of type "role" since --role-path was used'
            )
            self.galaxy.content_paths = self.options.roles_path
            # self.galaxy.options['content_type'] = 'role'
            self.galaxy.options.content_type = 'role'

            # FIXME - add more types here, PoC is just role/module

        if len(self.args) == 0 and self.galaxy_file is None:
            # the user needs to specify one of either --role-file or specify a single user/role name
            raise cli_exceptions.CliOptionsError(
                "- you must specify user/content name or a ansible-galaxy.yml file"
            )

        no_deps = self.options.no_deps
        force = self.options.force

        content_left = []

        # FIXME - Need to handle role files here for backwards compat

        # roles were specified directly, so we'll just go out grab them
        # (and their dependencies, unless the user doesn't want us to).
        for content in self.args:
            galaxy_content = GalaxyContent.yaml_parse(content.strip())
            galaxy_content["type"] = self.options.content_type
            self.log.debug('content install galaxy_content: %s',
                           galaxy_content)
            content_left.append(GalaxyContent(self.galaxy, **galaxy_content))

        for content in content_left:
            # only process roles in roles files when names matches if given

            # FIXME - not sure how to handle this scenario for ansible galaxy files
            #         here or if we even want to handle that scenario because of
            #         the galaxy content allowing blank repos to be inspected
            #
            #         maybe we want this but only for role types for backwards
            #         compat
            #
            # if role_file and self.args and role.name not in self.args:
            #    display.vvv('Skipping role %s' % role.name)
            #    continue

            log.debug('Processing %s %s ', content.content_type, content.name)

            # FIXME - Unsure if we want to handle the install info for all galaxy
            #         content. Skipping for non-role types for now.
            if content.content_type == "role":
                if content.install_info is not None:
                    if content.install_info[
                            'version'] != content.version or force:
                        if force:
                            self.display(
                                '- changing role %s from %s to %s' %
                                (content.name, content.install_info['version'],
                                 content.version or "unspecified"))
                            content.remove()
                        else:
                            log.warn(
                                '- %s (%s) is already installed - use --force to change version to %s',
                                content.name, content.install_info['version'],
                                content.version or "unspecified")
                            continue
                    else:
                        if not force:
                            self.display(
                                '- %s is already installed, skipping.' %
                                str(content))
                            continue

            try:
                installed = content.install()
            except cli_exceptions.GalaxyCliError as e:
                log.warning("- %s was NOT installed successfully: %s ",
                            content.name, str(e))
                self.exit_without_ignore()
                continue

            # install dependencies, if we want them
            # FIXME - Galaxy Content Types handle dependencies in the GalaxyContent type itself because
            #         a content repo can contain many types and many of any single type and it's just
            #         easier to have that introspection there. In the future this should be more
            #         unified and have a clean API
            if content.content_type == "role":
                if not no_deps and installed:
                    if not content.metadata:
                        log.warning(
                            "Meta file %s is empty. Skipping dependencies.",
                            content.path)
                    else:
                        role_dependencies = content.metadata.get(
                            'dependencies') or []
                        for dep in role_dependencies:
                            log.debug('Installing dep %s', dep)
                            dep_info = GalaxyContent.yaml_parse(dep)
                            dep_role = GalaxyContent(self.galaxy, **dep_info)
                            if '.' not in dep_role.name and '.' not in dep_role.src and dep_role.scm is None:
                                # we know we can skip this, as it's not going to
                                # be found on galaxy.ansible.com
                                continue
                            if dep_role.install_info is None:
                                if dep_role not in content_left:
                                    self.display('- adding dependency: %s' %
                                                 str(dep_role))
                                    content_left.append(dep_role)
                                else:
                                    self.display(
                                        '- dependency %s already pending installation.'
                                        % dep_role.name)
                            else:
                                if dep_role.install_info[
                                        'version'] != dep_role.version:
                                    log.warning(
                                        '- dependency %s from role %s differs from already installed version (%s), skipping',
                                        str(dep_role), content.name,
                                        dep_role.install_info['version'])
                                else:
                                    self.display(
                                        '- dependency %s is already installed, skipping.'
                                        % dep_role.name)

            if not installed:
                log.warning("- %s was NOT installed successfully.",
                            content.name)
                self.exit_without_ignore()

        return 0
Exemplo n.º 10
0
    def execute_init(self):
        """
        creates the skeleton framework of a role that complies with the galaxy metadata format.
        """

        init_path = self.options.init_path
        force = self.options.force
        role_skeleton_path = self.options.role_skeleton

        role_name = self.args.pop(0).strip() if self.args else None
        if not role_name:
            raise cli_exceptions.CliOptionsError(
                "- no role name specified for init")
        role_path = os.path.join(init_path, role_name)
        if os.path.exists(role_path):
            if os.path.isfile(role_path):
                raise cli_exceptions.GalaxyCliError(
                    "- the path %s already exists, but is a file - aborting" %
                    role_path)
            elif not force:
                raise cli_exceptions.GalaxyCliError(
                    "- the directory %s already exists."
                    "you can use --force to re-initialize this directory,\n"
                    "however it will reset any main.yml files that may have\n"
                    "been modified there already." % role_path)

        # FIXME(akl): role_skeleton stuff should probably be a module or two and a few classes instead of inline here
        # role_skeleton ends mostly being a list of file paths to copy
        inject_data = dict(
            role_name=role_name,
            author='your name',
            description='your description',
            company='your company (optional)',
            license='license (GPLv2, CC-BY, etc)',
            issue_tracker_url='http://example.com/issue/tracker',
            min_ansible_version='1.2',
            role_type=self.options.role_type)

        import pprint
        self.log.debug('inject_data: %s', pprint.pformat(inject_data))

        # create role directory
        if not os.path.exists(role_path):
            os.makedirs(role_path)

        if role_skeleton_path is not None:
            skeleton_ignore_expressions = runtime.GALAXY_ROLE_SKELETON_IGNORE
        else:
            this_dir, this_filename = os.path.split(__file__)

            type_path = getattr(self.options, 'role_type', "default")
            role_skeleton_path = os.path.join(this_dir, '../',
                                              'data/role_skelton', type_path)

            self.log.debug('role_skeleton_path: %s', role_skeleton_path)

            skeleton_ignore_expressions = ['^.*/.git_keep$']

        role_skeleton = os.path.expanduser(role_skeleton_path)

        self.log.debug('role_skeleton: %s', role_skeleton)
        skeleton_ignore_re = [
            re.compile(x) for x in skeleton_ignore_expressions
        ]

        template_env = Environment(loader=FileSystemLoader(role_skeleton))

        # TODO: mv elsewhere, this is main role install logic
        for root, dirs, files in os.walk(role_skeleton, topdown=True):
            rel_root = os.path.relpath(root, role_skeleton)
            in_templates_dir = rel_root.split(os.sep, 1)[0] == 'templates'
            dirs[:] = [
                d for d in dirs
                if not any(r.match(d) for r in skeleton_ignore_re)
            ]

            for f in files:
                filename, ext = os.path.splitext(f)
                if any(
                        r.match(os.path.join(rel_root, f))
                        for r in skeleton_ignore_re):
                    continue
                elif ext == ".j2" and not in_templates_dir:
                    src_template = os.path.join(rel_root, f)
                    dest_file = os.path.join(role_path, rel_root, filename)
                    template_env.get_template(src_template).stream(
                        inject_data).dump(dest_file)
                else:
                    f_rel_path = os.path.relpath(os.path.join(root, f),
                                                 role_skeleton)
                    shutil.copyfile(os.path.join(root, f),
                                    os.path.join(role_path, f_rel_path))

            for d in dirs:
                dir_path = os.path.join(role_path, rel_root, d)
                if not os.path.exists(dir_path):
                    os.makedirs(dir_path)

        self.display("- %s was created successfully" % role_name)
Exemplo n.º 11
0
    def execute_info(self):
        """
        prints out detailed information about an installed role as well as info available from the galaxy API.
        """

        if len(self.args) == 0:
            # the user needs to specify a role
            raise cli_exceptions.CliOptionsError("- you must specify a user/role name")

        content_path = self.options.roles_path

        data = ''

        log.debug('args=%s', self.args)

        galaxy_context = self._get_galaxy_context(self.options, self.config)

        for content_spec in self.args:

            content_username, repo_name, content_name = parse_content_name(content_spec)

            log.debug('content_spec=%s', content_spec)
            log.debug('content_username=%s', content_username)
            log.debug('repo_name=%s', repo_name)
            log.debug('content_name=%s', content_name)

            repo_name = repo_name or content_name
            log.debug('repo_name2=%s', repo_name)

            content_info = {'path': content_path}
            gr = GalaxyContent(galaxy_context, content_spec)

            install_info = gr.install_info
            if install_info:
                if 'version' in install_info:
                    install_info['intalled_version'] = install_info['version']
                    del install_info['version']
                content_info.update(install_info)

            remote_data = False
            if not self.options.offline:
                remote_data = self.api.lookup_content_repo_by_name(content_username, repo_name)

            if remote_data:
                content_info.update(remote_data)

            if gr.metadata:
                content_info.update(gr.metadata)

            # role_spec = yaml_parse({'role': role})
            # if role_spec:
            #     role_info.update(role_spec)

            data = self._display_content_info(content_info)
            # data = self._display_role_info(content_info)
            # FIXME: This is broken in both 1.9 and 2.0 as
            # _display_role_info() always returns something
            if not data:
                data = u"\n- the content %s was not found" % content_spec

        self.display(data)