Exemple #1
0
    def execute_info(self):
        """
        Executes the info action. This action 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 AnsibleOptionsError("- you must specify a user/role name")

        roles_path = self.get_opt("roles_path")

        for role in self.args:

            role_info = {}
            gr = GalaxyRole(self.galaxy, role)
            #self.galaxy.add_role(gr)

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

            remote_data = False
            if self.api:
                remote_data = self.api.lookup_role_by_name(role, False)

            if remote_data:
                role_info.update(remote_data)

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

            req = RoleRequirement()
            __, __, role_spec = req.parse({'role': role})
            if role_spec:
                role_info.update(role_spec)

            if role_info:
                self.display.display("- %s:" % (role))
                for k in sorted(role_info.keys()):

                    if k in self.SKIP_INFO_KEYS:
                        continue

                    if isinstance(role_info[k], dict):
                        self.display.display("\t%s: " % (k))
                        for key in sorted(role_info[k].keys()):
                            if key in self.SKIP_INFO_KEYS:
                                continue
                            self.display.display("\t\t%s: %s" %
                                                 (key, role_info[k][key]))
                    else:
                        self.display.display("\t%s: %s" % (k, role_info[k]))
            else:
                self.display.display("- the role %s was not found" % role)
Exemple #2
0
    def execute_info(self):
        """
        Executes the info action. This action 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 AnsibleOptionsError("- you must specify a user/role name")

        roles_path = self.get_opt("roles_path")

        for role in self.args:

            role_info = {}
            gr = GalaxyRole(self.galaxy, role)
            #self.galaxy.add_role(gr)

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

            remote_data = False
            if self.api:
                remote_data = self.api.lookup_role_by_name(role, False)

            if remote_data:
                role_info.update(remote_data)

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

            req = RoleRequirement()
            __, __, role_spec= req.parse({'role': role})
            if role_spec:
                role_info.update(role_spec)

            if role_info:
                self.display.display("- %s:" % (role))
                for k in sorted(role_info.keys()):

                    if k in self.SKIP_INFO_KEYS:
                        continue

                    if isinstance(role_info[k], dict):
                        self.display.display("\t%s: " % (k))
                        for key in sorted(role_info[k].keys()):
                            if key in self.SKIP_INFO_KEYS:
                                continue
                            self.display.display("\t\t%s: %s" % (key, role_info[k][key]))
                    else:
                        self.display.display("\t%s: %s" % (k, role_info[k]))
            else:
                self.display.display("- the role %s was not found" % role)
    def execute_info(self):
        """
        Executes the info action. This action 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 AnsibleOptionsError("- you must specify a user/role name")

        roles_path = self.get_opt("roles_path")

        data = ''
        for role in self.args:

            role_info = {'path': roles_path}
            gr = GalaxyRole(self.galaxy, role)

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

            remote_data = False
            if self.api:
                remote_data = self.api.lookup_role_by_name(role, False)

            if remote_data:
                role_info.update(remote_data)

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

            req = RoleRequirement()
            role_spec= req.role_yaml_parse({'role': role})
            if role_spec:
                role_info.update(role_spec)

            data = self._display_role_info(role_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 role %s was not found" % role

        self.pager(data)
Exemple #4
0
    def execute_info(self):
        """
        Executes the info action. This action 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 AnsibleOptionsError("- you must specify a user/role name")

        roles_path = self.get_opt("roles_path")

        data = ''
        for role in self.args:

            role_info = {'path': roles_path}
            gr = GalaxyRole(self.galaxy, role)

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

            remote_data = False
            if not self.options.offline:
                remote_data = self.api.lookup_role_by_name(role, False)

            if remote_data:
                role_info.update(remote_data)

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

            req = RoleRequirement()
            role_spec = req.role_yaml_parse({'role': role})
            if role_spec:
                role_info.update(role_spec)

            data = self._display_role_info(role_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 role %s was not found" % role

        self.pager(data)
Exemple #5
0
def test_git_ssh_role_url():
    role = RoleRequirement.role_yaml_parse(
        '[email protected]:mygroup/ansible-base.git')
    assert role['src'] == '[email protected]:mygroup/ansible-base.git'
    assert role['name'].startswith('ansible-base')
    assert role['scm'] is None
    assert role['version'] is None
Exemple #6
0
    def _load_dependencies(self, attr, ds):
        '''
        This is a helper loading function for the dependencies list,
        which returns a list of RoleInclude objects
        '''

        roles = []
        if ds:
            if not isinstance(ds, list):
                raise AnsibleParserError("Expected role dependencies to be a list.", obj=self._ds)

            for role_def in ds:
                if isinstance(role_def, string_types) or 'role' in role_def or 'name' in role_def:
                    roles.append(role_def)
                    continue
                try:
                    # role_def is new style: { src: 'galaxy.role,version,name', other_vars: "here" }
                    def_parsed = RoleRequirement.role_yaml_parse(role_def)
                    if def_parsed.get('name'):
                        role_def['name'] = def_parsed['name']
                    roles.append(role_def)
                except AnsibleError as exc:
                    raise AnsibleParserError(str(exc), obj=role_def)

        current_role_path = None
        if self._owner:
            current_role_path = os.path.dirname(self._owner._role_path)

        try:
            return load_list_of_roles(roles, play=self._owner._play, current_role_path=current_role_path, variable_manager=self._variable_manager,
                                      loader=self._loader)
        except AssertionError:
            raise AnsibleParserError("A malformed list of role dependencies was encountered.", obj=self._ds)
Exemple #7
0
    def _load_dependencies(self, attr, ds):
        '''
        This is a helper loading function for the dependencies list,
        which returns a list of RoleInclude objects
        '''

        roles = []
        if ds:
            if not isinstance(ds, list):
                raise AnsibleParserError("Expected role dependencies to be a list.", obj=self._ds) 
                
            for role_def in ds: 
                 if isinstance(role_def, string_types) or 'role' in role_def or 'name' in role_def:
                     roles.append(role_def)   
                     continue
                 try:   
                    # role_def is new style: { src: 'galaxy.role,version,name', other_vars: "here" }
                    def_parsed = RoleRequirement.role_yaml_parse(role_def)
                    if def_parsed.get('name'):
                        role_def['name'] = def_parsed['name']  
                    roles.append(role_def)    
                 except AnsibleError as exc:
                     raise AnsibleParserError(str(exc), obj=role_def) 

        current_role_path = None
        if self._owner:
            current_role_path = os.path.dirname(self._owner._role_path)
       
        try:
            return load_list_of_roles(roles, play=self._owner._play, current_role_path=current_role_path, variable_manager=self._variable_manager, loader=self._loader)
        except AssertionError:
            raise AnsibleParserError("A malformed list of role dependencies was encountered.", obj=self._ds)
Exemple #8
0
    def execute_info(self):
        """
        Executes the info action. This action 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 AnsibleOptionsError("- you must specify a user/role name")

        roles_path = self.get_opt("roles_path")

        data = ''
        for role in self.args:

            role_info = {}
            gr = GalaxyRole(self.galaxy, role)
            #self.galaxy.add_role(gr)

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

            remote_data = False
            if self.api:
                remote_data = self.api.lookup_role_by_name(role, False)

            if remote_data:
                role_info.update(remote_data)

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

            req = RoleRequirement()
            __, __, role_spec= req.parse({'role': role})
            if role_spec:
                role_info.update(role_spec)

            data += self._display_role_info(role_info)
            if not data:
                data += "\n- the role %s was not found" % role

        self.pager(data)
Exemple #9
0
    def load(data, play, current_role_path=None, parent_role=None, variable_manager=None, loader=None):

        assert isinstance(data, string_types) or isinstance(data, dict) or isinstance(data, AnsibleBaseYAMLObject)
        if isinstance(data, string_types) and ',' in data:
            data = RoleRequirement.role_spec_parse(data)

        ri = RoleInclude(play=play, role_basedir=current_role_path, variable_manager=variable_manager, loader=loader)
        return ri.load_data(data, variable_manager=variable_manager, loader=loader)
Exemple #10
0
def test_git_version_role_url():
    role = RoleRequirement.role_yaml_parse(
        'git+https://github.com/geerlingguy/ansible-role-composer.git,main')
    assert role[
        'src'] == 'https://github.com/geerlingguy/ansible-role-composer.git'
    assert role['name'] == 'ansible-role-composer'
    assert role['scm'] == 'git'
    assert role['version'] == 'main'
Exemple #11
0
def test_token_role_url():
    role = RoleRequirement.role_yaml_parse(
        'git+https://gitlab+deploy-token-312644:[email protected]/akasurde/ansible-demo'
    )
    assert role[
        'src'] == 'https://gitlab+deploy-token-312644:[email protected]/akasurde/ansible-demo'
    assert role['name'].startswith('ansible-demo')
    assert role['scm'] == 'git'
    assert role['version'] is None
Exemple #12
0
    def load(data, play, current_role_path=None, parent_role=None, variable_manager=None, loader=None):

        if not (isinstance(data, string_types) or isinstance(data, dict) or isinstance(data, AnsibleBaseYAMLObject)):
            raise AnsibleParserError("Invalid role definition: %s" % to_native(data))

        if isinstance(data, string_types) and ',' in data:
            data = RoleRequirement.role_spec_parse(data)

        ri = RoleInclude(play=play, role_basedir=current_role_path, variable_manager=variable_manager, loader=loader)
        return ri.load_data(data, variable_manager=variable_manager, loader=loader)
Exemple #13
0
    def execute_info(self):
        """
        prints out detailed information about an installed role as well as info available from the galaxy API.
        """

        roles_path = context.CLIARGS['roles_path']

        data = ''
        for role in context.CLIARGS['args']:

            role_info = {'path': roles_path}
            gr = GalaxyRole(self.galaxy, role)

            install_info = gr.install_info
            if install_info:
                if 'version' in install_info:
                    install_info['installed_version'] = install_info['version']
                    del install_info['version']
                role_info.update(install_info)

            remote_data = False
            if not context.CLIARGS['offline']:
                remote_data = self.api.lookup_role_by_name(role, False)

            if remote_data:
                role_info.update(remote_data)

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

            req = RoleRequirement()
            role_spec = req.role_yaml_parse({'role': role})
            if role_spec:
                role_info.update(role_spec)

            data = self._display_role_info(role_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 role %s was not found" % role

        self.pager(data)
    def _get_role_dependencies(self, role_path):
        role_dependencies = []
        dep_info = None
        meta_path = os.path.join(role_path, self.META_MAIN)
        if os.path.isfile(meta_path):
            try:
                f = open(meta_path, 'r')
                metadata = yaml.safe_load(f)
                role_dependencies = metadata.get('dependencies') or []
            except (OSError, IOError) as IOe:
                display.vvv("Unable to load metadata for %s" % role_path)
                return False
            finally:
                f.close()
        if role_dependencies:
            for dep in role_dependencies:
                dep_req = RoleRequirement()
                dep_info = dep_req.role_yaml_parse(dep)

        return dep_info
Exemple #15
0
    def info(self):
        if len(self.repo) == 0:
            # the user needs to specify a role
            raise AnsibleOptionsError("- you must specify a user/role name")

        roles_path = self.options.roles_path

        data = []
        for role in self.repo:

            role_info = {'path': roles_path}
            gr = GalaxyRole(self.galaxy, role)

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

            remote_data = False
            api = GalaxyAPI(self.galaxy)
            if not self.options.offline:
                remote_data = api.lookup_role_by_name(role, False)

            if remote_data:
                role_info.update(remote_data)

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

            req = RoleRequirement()
            role_spec = req.role_yaml_parse({'role': role})
            if role_spec:
                role_info.update(role_spec)

            data.append(role_info)

        return data
    def _load_dependencies(self, attr, ds):
        '''
        This is a helper loading function for the dependencies list,
        which returns a list of RoleInclude objects
        '''

        roles = []
        if ds:
            if not isinstance(ds, list):
                raise AnsibleParserError("Expected role dependencies to be a list.", obj=self._ds)

            for role_def in ds:
                if isinstance(role_def, string_types) or 'role' in role_def or 'name' in role_def:
                    roles.append(role_def)
                    continue
                try:
                    # role_def is new style: { src: 'galaxy.role,version,name', other_vars: "here" }
                    def_parsed = RoleRequirement.role_yaml_parse(role_def)
                    if def_parsed.get('name'):
                        role_def['name'] = def_parsed['name']
                    roles.append(role_def)
                except AnsibleError as exc:
                    raise AnsibleParserError(to_native(exc), obj=role_def, orig_exc=exc)

        current_role_path = None
        collection_search_list = None

        if self._owner:
            current_role_path = os.path.dirname(self._owner._role_path)

            # if the calling role has a collections search path defined, consult it
            collection_search_list = self._owner.collections[:] or []

            # if the calling role is a collection role, ensure that its containing collection is searched first
            owner_collection = self._owner._role_collection
            if owner_collection:
                collection_search_list = [c for c in collection_search_list if c != owner_collection]
                collection_search_list.insert(0, owner_collection)
            # ensure fallback role search works
            if 'ansible.legacy' not in collection_search_list:
                collection_search_list.append('ansible.legacy')

        try:
            return load_list_of_roles(roles, play=self._owner._play, current_role_path=current_role_path,
                                      variable_manager=self._variable_manager, loader=self._loader,
                                      collection_search_list=collection_search_list)
        except AssertionError as e:
            raise AnsibleParserError("A malformed list of role dependencies was encountered.", obj=self._ds, orig_exc=e)
Exemple #17
0
def add_dependencies(import_task, dependencies, role):
    if not dependencies:
        return
    add_message(import_task, u"INFO", u"Adding dependencies")
    if not isinstance(dependencies, list):
        add_message(
            import_task, "ERROR", "Expected dependencies to be a list, "
            "instead got %s" % type(dependencies).__name__)
        return
    dep_names = []
    for dep in dependencies:
        try:
            dep_parsed = RoleRequirement.role_yaml_parse(dep)
            if not dep_parsed.get('name'):
                raise Exception(u"Unable to determine name for dependency")
            names = dep_parsed['name'].split(".")
            if len(names) < 2:
                raise Exception(
                    u"Expecting dependency name format to match 'username.role_name', "
                    u"instead got %s" % dep_parsed['name'])
            if len(names) > 2:
                # the username contains .
                name = names.pop()
                namespace = '.'.join(names)
            else:
                namespace = names[0]
                name = names[1]
            try:
                dep_role = Role.objects.get(namespace=namespace, name=name)
                role.dependencies.add(dep_role)
                dep_names.append(dep_parsed['name'])
            except Exception as exc:
                logger.error("Error loading dependencies %s" % unicode(exc))
                raise Exception(u"Role dependency not found: %s.%s" %
                                (namespace, name))
        except (AnsibleError, Exception) as exc:
            add_message(import_task, u'ERROR',
                        u'Error parsing dependency %s' % unicode(exc))

    # Remove deps that are no longer listed in the metadata
    for dep in role.dependencies.all():
        dep_name = dep.__unicode__()
        if dep_name not in dep_names:
            role.dependencies.remove(dep)
Exemple #18
0
    def load(data,
             play,
             current_role_path=None,
             parent_role=None,
             variable_manager=None,
             loader=None):

        if not (isinstance(data, string_types) or isinstance(data, dict)
                or isinstance(data, AnsibleBaseYAMLObject)):
            raise AnsibleParserError("Invalid role definition: %s" %
                                     to_native(data))

        if isinstance(data, string_types) and ',' in data:
            data = RoleRequirement.role_spec_parse(data)

        ri = RoleInclude(play=play,
                         role_basedir=current_role_path,
                         variable_manager=variable_manager,
                         loader=loader)
        return ri.load_data(data,
                            variable_manager=variable_manager,
                            loader=loader)
Exemple #19
0
    def install(self):
        # the file is a tar, so open it that way and extract it
        # to the specified (or default) roles directory
        local_file = False

        if self.scm:
            # create tar file from scm url
            tmp_file = RoleRequirement.scm_archive_role(**self.spec)
        elif self.src:
            if  os.path.isfile(self.src):
                # installing a local tar.gz
                local_file = True
                tmp_file = self.src
            elif '://' in self.src:
                role_data = self.src
                tmp_file = self.fetch(role_data)
            else:
                api = GalaxyAPI(self.galaxy)
                role_data = api.lookup_role_by_name(self.src)
                if not role_data:
                    raise AnsibleError("- sorry, %s was not found on %s." % (self.src, api.api_server))

                role_versions = api.fetch_role_related('versions', role_data['id'])
                if not self.version:
                    # convert the version names to LooseVersion objects
                    # and sort them to get the latest version. If there
                    # are no versions in the list, we'll grab the head
                    # of the master branch
                    if len(role_versions) > 0:
                        loose_versions = [LooseVersion(a.get('name',None)) for a in role_versions]
                        loose_versions.sort()
                        self.version = str(loose_versions[-1])
                    elif role_data.get('github_branch', None):
                        self.version = role_data['github_branch']
                    else:
                        self.version = 'master' 
                elif self.version != 'master':
                    if role_versions and self.version not in [a.get('name', None) for a in role_versions]:
                        raise AnsibleError("- the specified version (%s) of %s was not found in the list of available versions (%s)." % (self.version, self.name, role_versions))

                tmp_file = self.fetch(role_data)

        else:
           raise AnsibleError("No valid role data found")


        if tmp_file:

            display.debug("installing from %s" % tmp_file)

            if not tarfile.is_tarfile(tmp_file):
                raise AnsibleError("the file downloaded was not a tar.gz")
            else:
                if tmp_file.endswith('.gz'):
                    role_tar_file = tarfile.open(tmp_file, "r:gz")
                else:
                    role_tar_file = tarfile.open(tmp_file, "r")
                # verify the role's meta file
                meta_file = None
                members = role_tar_file.getmembers()
                # next find the metadata file
                for member in members:
                    if self.META_MAIN in member.name:
                        meta_file = member
                        break
                if not meta_file:
                    raise AnsibleError("this role does not appear to have a meta/main.yml file.")
                else:
                    try:
                        self._metadata = yaml.safe_load(role_tar_file.extractfile(meta_file))
                    except:
                        raise AnsibleError("this role does not appear to have a valid meta/main.yml file.")

                # we strip off the top-level directory for all of the files contained within
                # the tar file here, since the default is 'github_repo-target', and change it
                # to the specified role's name
                installed = False
                while not installed:
                    display.display("- extracting %s to %s" % (self.name, self.path))
                    try:
                        if os.path.exists(self.path):
                            if not os.path.isdir(self.path):
                                raise AnsibleError("the specified roles path exists and is not a directory.")
                            elif not getattr(self.options, "force", False):
                                raise AnsibleError("the specified role %s appears to already exist. Use --force to replace it." % self.name)
                            else:
                                # using --force, remove the old path
                                if not self.remove():
                                    raise AnsibleError("%s doesn't appear to contain a role.\n  please remove this directory manually if you really want to put the role here." % self.path)
                        else:
                            os.makedirs(self.path)

                        # now we do the actual extraction to the path
                        for member in members:
                            # we only extract files, and remove any relative path
                            # bits that might be in the file for security purposes
                            # and drop the leading directory, as mentioned above
                            if member.isreg() or member.issym():
                                parts = member.name.split(os.sep)[1:]
                                final_parts = []
                                for part in parts:
                                    if part != '..' and '~' not in part and '$' not in part:
                                        final_parts.append(part)
                                member.name = os.path.join(*final_parts)
                                role_tar_file.extract(member, self.path)

                        # write out the install info file for later use
                        self._write_galaxy_install_info()
                        installed = True
                    except OSError as e:
                        error = True
                        if e[0] == 13 and len(self.paths) > 1:
                            current = self.paths.index(self.path)
                            nextidx = current + 1
                            if len(self.paths) >= current:
                                self.path = self.paths[nextidx]
                                error = False
                        if error:
                            raise AnsibleError("Could not update files in %s: %s" % (self.path, str(e)))

                # return the parsed yaml metadata
                display.display("- %s was installed successfully" % self.name)
                if not local_file:
                    try:
                        os.unlink(tmp_file)
                    except (OSError,IOError) as e:
                        display.warning("Unable to remove tmp file (%s): %s" % (tmp_file, str(e)))
                return True

        return False
Exemple #20
0
    def install(self):

        if self.scm:
            # create tar file from scm url
            tmp_file = RoleRequirement.scm_archive_role(
                keep_scm_meta=context.CLIARGS['keep_scm_meta'], **self.spec)
        elif self.src:
            if os.path.isfile(self.src):
                tmp_file = self.src
            elif '://' in self.src:
                role_data = self.src
                tmp_file = self.fetch(role_data)
            else:
                api = GalaxyAPI(self.galaxy, 'role_default', C.GALAXY_SERVER)
                role_data = api.lookup_role_by_name(self.src)
                if not role_data:
                    raise AnsibleError("- sorry, %s was not found on %s." %
                                       (self.src, api.api_server))

                if role_data.get('role_type') == 'APP':
                    # Container Role
                    display.warning(
                        "%s is a Container App role, and should only be installed using Ansible "
                        "Container" % self.name)

                role_versions = api.fetch_role_related('versions',
                                                       role_data['id'])
                if not self.version:
                    # convert the version names to LooseVersion objects
                    # and sort them to get the latest version. If there
                    # are no versions in the list, we'll grab the head
                    # of the master branch
                    if len(role_versions) > 0:
                        loose_versions = [
                            LooseVersion(a.get('name', None))
                            for a in role_versions
                        ]
                        try:
                            loose_versions.sort()
                        except TypeError:
                            raise AnsibleError(
                                'Unable to compare role versions (%s) to determine the most recent version due to incompatible version formats. '
                                'Please contact the role author to resolve versioning conflicts, or specify an explicit role version to '
                                'install.' %
                                ', '.join([v.vstring for v in loose_versions]))
                        self.version = to_text(loose_versions[-1])
                    elif role_data.get('github_branch', None):
                        self.version = role_data['github_branch']
                    else:
                        self.version = 'master'
                elif self.version != 'master':
                    if role_versions and to_text(self.version) not in [
                            a.get('name', None) for a in role_versions
                    ]:
                        raise AnsibleError(
                            "- the specified version (%s) of %s was not found in the list of available versions (%s)."
                            % (self.version, self.name, role_versions))

                # check if there's a source link for our role_version
                for role_version in role_versions:
                    if role_version[
                            'name'] == self.version and 'source' in role_version:
                        self.src = role_version['source']

                tmp_file = self.fetch(role_data)

        else:
            raise AnsibleError("No valid role data found")

        if tmp_file:

            display.debug("installing from %s" % tmp_file)

            if not tarfile.is_tarfile(tmp_file):
                raise AnsibleError(
                    "the downloaded file does not appear to be a valid tar archive."
                )
            else:
                role_tar_file = tarfile.open(tmp_file, "r")
                # verify the role's meta file
                meta_file = None
                members = role_tar_file.getmembers()
                # next find the metadata file
                for member in members:
                    for meta_main in self.META_MAIN:
                        if meta_main in member.name:
                            # Look for parent of meta/main.yml
                            # Due to possibility of sub roles each containing meta/main.yml
                            # look for shortest length parent
                            meta_parent_dir = os.path.dirname(
                                os.path.dirname(member.name))
                            if not meta_file:
                                archive_parent_dir = meta_parent_dir
                                meta_file = member
                            else:
                                if len(meta_parent_dir) < len(
                                        archive_parent_dir):
                                    archive_parent_dir = meta_parent_dir
                                    meta_file = member
                if not meta_file:
                    raise AnsibleError(
                        "this role does not appear to have a meta/main.yml file."
                    )
                else:
                    try:
                        self._metadata = yaml.safe_load(
                            role_tar_file.extractfile(meta_file))
                    except Exception:
                        raise AnsibleError(
                            "this role does not appear to have a valid meta/main.yml file."
                        )

                # we strip off any higher-level directories for all of the files contained within
                # the tar file here. The default is 'github_repo-target'. Gerrit instances, on the other
                # hand, does not have a parent directory at all.
                installed = False
                while not installed:
                    display.display("- extracting %s to %s" %
                                    (self.name, self.path))
                    try:
                        if os.path.exists(self.path):
                            if not os.path.isdir(self.path):
                                raise AnsibleError(
                                    "the specified roles path exists and is not a directory."
                                )
                            elif not context.CLIARGS.get("force", False):
                                raise AnsibleError(
                                    "the specified role %s appears to already exist. Use --force to replace it."
                                    % self.name)
                            else:
                                # using --force, remove the old path
                                if not self.remove():
                                    raise AnsibleError(
                                        "%s doesn't appear to contain a role.\n  please remove this directory manually if you really "
                                        "want to put the role here." %
                                        self.path)
                        else:
                            os.makedirs(self.path)

                        # now we do the actual extraction to the path
                        for member in members:
                            # we only extract files, and remove any relative path
                            # bits that might be in the file for security purposes
                            # and drop any containing directory, as mentioned above
                            if member.isreg() or member.issym():
                                parts = member.name.replace(
                                    archive_parent_dir, "", 1).split(os.sep)
                                final_parts = []
                                for part in parts:
                                    if part != '..' and '~' not in part and '$' not in part:
                                        final_parts.append(part)
                                member.name = os.path.join(*final_parts)
                                role_tar_file.extract(member, self.path)

                        # write out the install info file for later use
                        self._write_galaxy_install_info()
                        installed = True
                    except OSError as e:
                        error = True
                        if e.errno == errno.EACCES and len(self.paths) > 1:
                            current = self.paths.index(self.path)
                            if len(self.paths) > current:
                                self.path = self.paths[current + 1]
                                error = False
                        if error:
                            raise AnsibleError(
                                "Could not update files in %s: %s" %
                                (self.path, to_native(e)))

                # return the parsed yaml metadata
                display.display("- %s was installed successfully" % str(self))
                if not (self.src and os.path.isfile(self.src)):
                    try:
                        os.unlink(tmp_file)
                    except (OSError, IOError) as e:
                        display.warning(u"Unable to remove tmp file (%s): %s" %
                                        (tmp_file, to_text(e)))
                return True

        return False
Exemple #21
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 = context.CLIARGS['role_file']

        if not context.CLIARGS['args'] and role_file is None:
            # the user needs to specify one of either --role-file or specify a single user/role name
            raise AnsibleOptionsError(
                "- you must specify a user/role name or a roles file")

        no_deps = context.CLIARGS['no_deps']
        force = context.CLIARGS['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 AnsibleError(
                            "Unable to load data from the requirements file: %s"
                            % role_file)

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

                    for role in required_roles:
                        if "include" not in role:
                            role = RoleRequirement.role_yaml_parse(role)
                            display.vvv("found role %s in yaml file" %
                                        str(role))
                            if "name" not in role and "scm" not in role:
                                raise AnsibleError(
                                    "Must specify name or src for role")
                            roles_left.append(GalaxyRole(self.galaxy, **role))
                        else:
                            with open(role["include"]) as f_include:
                                try:
                                    roles_left += [
                                        GalaxyRole(self.galaxy, **r) for r in (
                                            RoleRequirement.role_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 AnsibleError(msg % (role_file, e))
                else:
                    raise AnsibleError("Invalid role requirements file")
                f.close()
            except (IOError, OSError) as e:
                raise AnsibleError('Unable to open %s: %s' %
                                   (role_file, to_native(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 context.CLIARGS['args']:
                role = RoleRequirement.role_yaml_parse(rname.strip())
                roles_left.append(GalaxyRole(self.galaxy, **role))

        for role in roles_left:
            # only process roles in roles files when names matches if given
            if role_file and context.CLIARGS[
                    'args'] and role.name not in context.CLIARGS['args']:
                display.vvv('Skipping role %s' % role.name)
                continue

            display.vvv('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:
                        display.display(
                            '- changing role %s from %s to %s' %
                            (role.name, role.install_info['version'],
                             role.version or "unspecified"))
                        role.remove()
                    else:
                        display.warning(
                            '- %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:
                        display.display(
                            '- %s is already installed, skipping.' % str(role))
                        continue

            try:
                installed = role.install()
            except AnsibleError as e:
                display.warning(u"- %s was NOT installed successfully: %s " %
                                (role.name, to_text(e)))
                self.exit_without_ignore()
                continue

            # install dependencies, if we want them
            if not no_deps and installed:
                if not role.metadata:
                    display.warning(
                        "Meta file %s is empty. Skipping dependencies." %
                        role.path)
                else:
                    role_dependencies = role.metadata.get('dependencies') or []
                    for dep in role_dependencies:
                        display.debug('Installing dep %s' % dep)
                        dep_req = RoleRequirement()
                        dep_info = dep_req.role_yaml_parse(dep)
                        dep_role = GalaxyRole(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:
                                display.display('- adding dependency: %s' %
                                                str(dep_role))
                                roles_left.append(dep_role)
                            else:
                                display.display(
                                    '- dependency %s already pending installation.'
                                    % dep_role.name)
                        else:
                            if dep_role.install_info[
                                    'version'] != dep_role.version:
                                display.warning(
                                    '- dependency %s from role %s differs from already installed version (%s), skipping'
                                    % (str(dep_role), role.name,
                                       dep_role.install_info['version']))
                            else:
                                display.display(
                                    '- dependency %s is already installed, skipping.'
                                    % dep_role.name)

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

        return 0
Exemple #22
0
def test_git_file_role_url():
    role = RoleRequirement.role_yaml_parse('git+file:///home/bennojoy/nginx')
    assert role['src'] == 'file:///home/bennojoy/nginx'
    assert role['name'] == 'nginx'
    assert role['scm'] == 'git'
    assert role['version'] is None
Exemple #23
0
    def execute_install(self):
        """
        Executes the installation action. The args list contains the
        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.get_opt("role_file", None)

        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 AnsibleOptionsError(
                "- you must specify a user/role name or a roles file")
        elif len(self.args) == 1 and role_file is not None:
            # using a role file is mutually exclusive of specifying
            # the role name on the command line
            raise AnsibleOptionsError(
                "- please specify a user/role name, or a roles file, but not both"
            )

        no_deps = self.get_opt("no_deps", False)
        force = self.get_opt('force', False)

        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 AnsibleError(
                            "Unable to load data from the requirements file: %s"
                            % role_file)

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

                    for role in required_roles:
                        if "include" not in role:
                            role = RoleRequirement.role_yaml_parse(role)
                            display.vvv("found role %s in yaml file" %
                                        str(role))
                            if "name" not in role and "scm" not in role:
                                raise AnsibleError(
                                    "Must specify name or src for role")
                            roles_left.append(GalaxyRole(self.galaxy, **role))
                        else:
                            with open(role["include"]) as f_include:
                                try:
                                    roles_left += [
                                        GalaxyRole(self.galaxy, **r)
                                        for r in map(
                                            RoleRequirement.role_yaml_parse,
                                            yaml.safe_load(f_include))
                                    ]
                                except Exception as e:
                                    msg = "Unable to load data from the include requirements file: %s %s"
                                    raise AnsibleError(msg % (role_file, e))
                else:
                    display.deprecated(
                        "going forward only the yaml format will be supported")
                    # roles listed in a file, one per line
                    for rline in f.readlines():
                        if rline.startswith("#") or rline.strip() == '':
                            continue
                        display.debug('found role %s in text file' %
                                      str(rline))
                        role = RoleRequirement.role_yaml_parse(rline.strip())
                        roles_left.append(GalaxyRole(self.galaxy, **role))
                f.close()
            except (IOError, OSError) as e:
                raise AnsibleError('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 = RoleRequirement.role_yaml_parse(rname.strip())
                roles_left.append(GalaxyRole(self.galaxy, **role))

        for role in roles_left:
            display.vvv('Installing 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:
                    if force:
                        display.display(
                            '- changing role %s from %s to %s' %
                            (role.name, role.install_info['version'],
                             role.version or "unspecified"))
                        role.remove()
                    else:
                        display.warning(
                            '- %s (%s) is already installed - use --force to change version to %s'
                            % (role.name, role.install_info['version'],
                               role.version or "unspecified"))
                        continue
                else:
                    display.display('- %s is already installed, skipping.' %
                                    str(role))
                    continue

            try:
                installed = role.install()
            except AnsibleError as e:
                display.warning("- %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:
                role_dependencies = role.metadata.get('dependencies') or []
                for dep in role_dependencies:
                    display.debug('Installing dep %s' % dep)
                    dep_req = RoleRequirement()
                    dep_info = dep_req.role_yaml_parse(dep)
                    dep_role = GalaxyRole(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:
                            display.display('- adding dependency: %s' %
                                            str(dep_role))
                            roles_left.append(dep_role)
                        else:
                            display.display(
                                '- dependency %s already pending installation.'
                                % dep_role.name)
                    else:
                        if dep_role.install_info['version'] != dep_role.version:
                            display.warning(
                                '- dependency %s from role %s differs from already installed version (%s), skipping'
                                % (str(dep_role), role.name,
                                   dep_role.install_info['version']))
                        else:
                            display.display(
                                '- dependency %s is already installed, skipping.'
                                % dep_role.name)

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

        return 0
Exemple #24
0
 def _role_to_temp_space(self, role_req):
     role_req_kwargs = RoleRequirement.role_yaml_parse(role_req.strip())
     role_obj = GalaxyRole(self._galaxy, **role_req_kwargs)
     installed = role_obj.install()
     return role_obj, installed
Exemple #25
0
    def install(self, book_id=None):
        """
        copy from ansible-galaxy
        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.repo) == 0 and role_file is None:
            # the user needs to specify one of either --role-file or specify a single user/role name
            raise AnsibleOptionsError("- 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 AnsibleError("Unable to load data from the requirements file: %s" % role_file)

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

                    for role in required_roles:
                        if "include" not in role:
                            role = RoleRequirement.role_yaml_parse(role)
                            if "name" not in role and "scm" not in role:
                                raise AnsibleError("Must specify name or src for role")
                            roles_left.append(GalaxyRole(self.galaxy, **role))
                        else:
                            with open(role["include"]) as f_include:
                                try:
                                    roles_left += [
                                        GalaxyRole(self.galaxy, **r) for r in
                                        (RoleRequirement.role_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 AnsibleError(msg % (role_file, e))
                else:
                    raise AnsibleError("Invalid role requirements file")
                f.close()
            except (IOError, OSError) as e:
                raise AnsibleError('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.repo:
                role = RoleRequirement.role_yaml_parse(rname.strip())
                roles_left.append(GalaxyRole(self.galaxy, **role))

        installed_role = []
        for role in roles_left:
            # only process roles in roles files when names matches if given
            if role_file and self.repo and role.name not in self.repo:
                print('Skipping role %s' % role.name)
                continue

            # 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:
                        print('- changing role %s from %s to %s' %
                                    (role.name, role.install_info['version'], role.version or "unspecified"))
                        role.remove()
                    else:
                        print('- %s (%s) is already installed - use --force to change version to %s' %
                                    (role.name, role.install_info['version'], role.version or "unspecified"))
                        installed_role.append(role.name)
                        continue
                else:
                    if not force:
                        print('- %s is already installed, skipping.' % str(role))
                        continue

            try:
                installed = role.install()
                if installed and book_id:
                    wk = Workspace()
                    documents = wk.import_book_from_dir(os.path.dirname(role.path), book_id)
                    for doc in documents:
                        if doc.get('role') != 'entry':
                            doc['path'] = '/roles' + doc.get('path')
                        print(doc['path'])
                        Playbook().collection.update_one({'path': doc.get('path')}, {'$set': doc}, upsert=True)

            except AnsibleError as e:
                print("- %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:
                    print("Meta file %s is empty. Skipping dependencies." % role.path)
                else:
                    role_dependencies = role.metadata.get('dependencies') or []
                    for dep in role_dependencies:
                        logger.debug('Installing dep %s' % dep)
                        dep_req = RoleRequirement()
                        dep_info = dep_req.role_yaml_parse(dep)
                        dep_role = GalaxyRole(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:
                                print('- adding dependency: %s' % str(dep_role))
                                roles_left.append(dep_role)
                            else:
                                print('- dependency %s already pending installation.' % dep_role.name)
                        else:
                            if dep_role.install_info['version'] != dep_role.version:
                                print(
                                    '- dependency %s from role %s differs from already installed version (%s), skipping' %
                                    (str(dep_role), role.name, dep_role.install_info['version']))
                            else:
                                print('- dependency %s is already installed, skipping.' % dep_role.name)

            if not installed:
                print("- %s was NOT installed successfully." % role.name)
                # self.exit_without_ignore()

        for role in installed_role:
            wk = Workspace()
            # wk.import_book_from_dir(self.options.roles_path)
        return 0
Exemple #26
0
    def execute_install(self):
        """
        Executes the installation action. The args list contains the
        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.get_opt("role_file", None)

        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 AnsibleOptionsError("- you must specify a user/role name or a roles file")
        elif len(self.args) == 1 and not role_file is None:
            # using a role file is mutually exclusive of specifying
            # the role name on the command line
            raise AnsibleOptionsError("- please specify a user/role name, or a roles file, but not both")

        no_deps    = self.get_opt("no_deps", False)
        force      = self.get_opt('force', False)
        roles_path = self.get_opt("roles_path")

        roles_done = []
        roles_left = []
        if role_file:
            self.display.debug('Getting roles from %s' % role_file)
            try:
                self.display.debug('Processing role file: %s' % role_file)
                f = open(role_file, 'r')
                if role_file.endswith('.yaml') or role_file.endswith('.yml'):
                    try:
                        rolesparsed = map(self.parse_requirements_files, yaml.safe_load(f))
                    except Exception as e:
                       raise AnsibleError("%s does not seem like a valid yaml file: %s" % (role_file, str(e)))
                    roles_left = [GalaxyRole(self.galaxy, **r) for r in rolesparsed]
                else:
                    # roles listed in a file, one per line
                    self.display.deprecated("Non yaml files for role requirements")
                    for rname in f.readlines():
                        if rname.startswith("#") or rname.strip() == '':
                            continue
                        roles_left.append(GalaxyRole(self.galaxy, rname.strip()))
                f.close()
            except (IOError,OSError) as e:
                raise AnsibleError("Unable to read requirements file (%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:
                roles_left.append(GalaxyRole(self.galaxy, rname.strip()))

        while len(roles_left) > 0:
            # query the galaxy API for the role data
            role_data = None
            role = roles_left.pop(0)
            role_path = role.path

            if role.install_info is not None and not force:
                self.display.display('- %s is already installed, skipping.' % role.name)
                continue

            if role_path:
                self.options.roles_path = role_path
            else:
                self.options.roles_path = roles_path

            self.display.debug('Installing role %s from %s' % (role.name, self.options.roles_path))

            tmp_file = None
            installed = False
            if role.src and os.path.isfile(role.src):
                # installing a local tar.gz
                tmp_file = role.src
            else:
                if role.scm:
                    # create tar file from scm url
                    tmp_file = GalaxyRole.scm_archive_role(role.scm, role.src, role.version, role.name)
                if role.src:
                    if '://' not in role.src:
                        role_data = self.api.lookup_role_by_name(role.src)
                        if not role_data:
                            self.display.warning("- sorry, %s was not found on %s." % (role.src, self.options.api_server))
                            self.exit_without_ignore()
                            continue

                        role_versions = self.api.fetch_role_related('versions', role_data['id'])
                        if not role.version:
                            # convert the version names to LooseVersion objects
                            # and sort them to get the latest version. If there
                            # are no versions in the list, we'll grab the head
                            # of the master branch
                            if len(role_versions) > 0:
                                loose_versions = [LooseVersion(a.get('name',None)) for a in role_versions]
                                loose_versions.sort()
                                role.version = str(loose_versions[-1])
                            else:
                                role.version = 'master'
                        elif role.version != 'master':
                            if role_versions and role.version not in [a.get('name', None) for a in role_versions]:
                                self.display.warning('role is %s' % role)
                                self.display.warning("- the specified version (%s) was not found in the list of available versions (%s)." % (role.version, role_versions))
                                self.exit_without_ignore()
                                continue

                    # download the role. if --no-deps was specified, we stop here,
                    # otherwise we recursively grab roles and all of their deps.
                    tmp_file = role.fetch(role_data)
            if tmp_file:
                installed = role.install(tmp_file)
                # we're done with the temp file, clean it up
                if tmp_file != role.src:
                    os.unlink(tmp_file)
                # install dependencies, if we want them
                if not no_deps and installed:
                    role_dependencies = role.metadata.get('dependencies', [])
                    for dep in role_dependencies:
                        self.display.debug('Installing dep %s' % dep)
                        dep_req = RoleRequirement()
                        __, dep_name, __ = dep_req.parse(dep)
                        dep_role = GalaxyRole(self.galaxy, name=dep_name)
                        if dep_role.install_info is None or force:
                            if dep_role not in roles_left:
                                self.display.display('- adding dependency: %s' % dep_name)
                                roles_left.append(GalaxyRole(self.galaxy, name=dep_name))
                            else:
                                self.display.display('- dependency %s already pending installation.' % dep_name)
                        else:
                            self.display.display('- dependency %s is already installed, skipping.' % dep_name)

            if not tmp_file or not installed:
                self.display.warning("- %s was NOT installed successfully." % role.name)
                self.exit_without_ignore()
        return 0
def role_to_temp_space(role_req, galaxy):
    role_req_kwargs = RoleRequirement.role_yaml_parse(role_req.strip())
    role_obj = GalaxyRole(galaxy, **role_req_kwargs)
    installed = role_obj.install()
    return role_obj, installed
Exemple #28
0
def test_null_role_url():
    role = RoleRequirement.role_yaml_parse('')
    assert role['src'] == ''
    assert role['name'] == ''
    assert role['scm'] is None
    assert role['version'] is None
Exemple #29
0
def test_tar_role_url(url):
    role = RoleRequirement.role_yaml_parse(url)
    assert role['src'] == url
    assert role['name'].startswith('main')
    assert role['scm'] is None
    assert role['version'] is None
    def execute_install(self):
        """
        Executes the installation action. The args list contains the
        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.get_opt("role_file", None)

        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 AnsibleOptionsError("- you must specify a user/role name or a roles file")
        elif len(self.args) == 1 and role_file is not None:
            # using a role file is mutually exclusive of specifying
            # the role name on the command line
            raise AnsibleOptionsError("- please specify a user/role name, or a roles file, but not both")

        no_deps    = self.get_opt("no_deps", False)
        force      = self.get_opt('force', False)

        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 AnsibleError("Unable to load data from the requirements file: %s" % role_file)

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

                    for role in required_roles:
                        role = RoleRequirement.role_yaml_parse(role)
                        display.vvv('found role %s in yaml file' % str(role))
                        if 'name' not in role and 'scm' not in role:
                            raise AnsibleError("Must specify name or src for role")
                        roles_left.append(GalaxyRole(self.galaxy, **role))
                else:
                    display.deprecated("going forward only the yaml format will be supported")
                    # roles listed in a file, one per line
                    for rline in f.readlines():
                        if rline.startswith("#") or rline.strip() == '':
                            continue
                        display.debug('found role %s in text file' % str(rline))
                        role = RoleRequirement.role_yaml_parse(rline.strip())
                        roles_left.append(GalaxyRole(self.galaxy, **role))
                f.close()
            except (IOError, OSError) as e:
                display.error('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 = RoleRequirement.role_yaml_parse(rname.strip())
                roles_left.append(GalaxyRole(self.galaxy, **role))

        for role in roles_left:
            display.vvv('Installing role %s ' % role.name)
            # query the galaxy API for the role data

            if role.install_info is not None and not force:
                display.display('- %s is already installed, skipping.' % role.name)
                continue

            try:
                installed = role.install()
            except AnsibleError as e:
                display.warning("- %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:
                role_dependencies = role.metadata.get('dependencies') or []
                for dep in role_dependencies:
                    display.debug('Installing dep %s' % dep)
                    dep_req = RoleRequirement()
                    dep_info = dep_req.role_yaml_parse(dep)
                    dep_role = GalaxyRole(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 or force:
                        if dep_role not in roles_left:
                            display.display('- adding dependency: %s' % dep_role.name)
                            roles_left.append(dep_role)
                        else:
                            display.display('- dependency %s already pending installation.' % dep_role.name)
                    else:
                        display.display('- dependency %s is already installed, skipping.' % dep_role.name)

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

        return 0
Exemple #31
0
    def install(self):
        # the file is a tar, so open it that way and extract it
        # to the specified (or default) roles directory

        if self.scm:
            # create tar file from scm url
            tmp_file = RoleRequirement.scm_archive_role(**self.spec)
        elif self.src:
            if  os.path.isfile(self.src):
                # installing a local tar.gz
                tmp_file = self.src
            elif '://' in self.src:
                role_data = self.src
                tmp_file = self.fetch(role_data)
            else:
                api = GalaxyAPI(self.galaxy)
                role_data = api.lookup_role_by_name(self.src)
                if not role_data:
                    raise AnsibleError("- sorry, %s was not found on %s." % (self.src, api.api_server))

                role_versions = api.fetch_role_related('versions', role_data['id'])
                if not self.version:
                    # convert the version names to LooseVersion objects
                    # and sort them to get the latest version. If there
                    # are no versions in the list, we'll grab the head
                    # of the master branch
                    if len(role_versions) > 0:
                        loose_versions = [LooseVersion(a.get('name',None)) for a in role_versions]
                        loose_versions.sort()
                        self.version = str(loose_versions[-1])
                    elif role_data.get('github_branch', None):
                        self.version = role_data['github_branch']
                    else:
                        self.version = 'master' 
                elif self.version != 'master':
                    if role_versions and self.version not in [a.get('name', None) for a in role_versions]:
                        raise AnsibleError("- the specified version (%s) of %s was not found in the list of available versions (%s)." % (self.version, self.name, role_versions))

                tmp_file = self.fetch(role_data)

        else:
           raise AnsibleError("No valid role data found")


        if tmp_file:

            display.debug("installing from %s" % tmp_file)

            if not tarfile.is_tarfile(tmp_file):
                raise AnsibleError("the file downloaded was not a tar.gz")
            else:
                if tmp_file.endswith('.gz'):
                    role_tar_file = tarfile.open(tmp_file, "r:gz")
                else:
                    role_tar_file = tarfile.open(tmp_file, "r")
                # verify the role's meta file
                meta_file = None
                members = role_tar_file.getmembers()
                # next find the metadata file
                for member in members:
                    if self.META_MAIN in member.name:
                        meta_file = member
                        break
                if not meta_file:
                    raise AnsibleError("this role does not appear to have a meta/main.yml file.")
                else:
                    try:
                        self._metadata = yaml.safe_load(role_tar_file.extractfile(meta_file))
                    except:
                        raise AnsibleError("this role does not appear to have a valid meta/main.yml file.")

                # we strip off the top-level directory for all of the files contained within
                # the tar file here, since the default is 'github_repo-target', and change it
                # to the specified role's name
                display.display("- extracting %s to %s" % (self.name, self.path))
                try:
                    if os.path.exists(self.path):
                        if not os.path.isdir(self.path):
                            raise AnsibleError("the specified roles path exists and is not a directory.")
                        elif not getattr(self.options, "force", False):
                            raise AnsibleError("the specified role %s appears to already exist. Use --force to replace it." % self.name)
                        else:
                            # using --force, remove the old path
                            if not self.remove():
                                raise AnsibleError("%s doesn't appear to contain a role.\n  please remove this directory manually if you really want to put the role here." % self.path)
                    else:
                        os.makedirs(self.path)

                    # now we do the actual extraction to the path
                    for member in members:
                        # we only extract files, and remove any relative path
                        # bits that might be in the file for security purposes
                        # and drop the leading directory, as mentioned above
                        if member.isreg() or member.issym():
                            parts = member.name.split(os.sep)[1:]
                            final_parts = []
                            for part in parts:
                                if part != '..' and '~' not in part and '$' not in part:
                                    final_parts.append(part)
                            member.name = os.path.join(*final_parts)
                            role_tar_file.extract(member, self.path)

                    # write out the install info file for later use
                    self._write_galaxy_install_info()
                except OSError as e:
                   raise AnsibleError("Could not update files in %s: %s" % (self.path, str(e)))

                # return the parsed yaml metadata
                display.display("- %s was installed successfully" % self.name)
                try:
                    os.unlink(tmp_file)
                except (OSError,IOError) as e:
                    display.warning("Unable to remove tmp file (%s): %s" % (tmp_file, str(e)))
                return True

        return False
Exemple #32
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 archive file.
        """
        if context.CLIARGS['type'] == 'collection':
            collections = context.CLIARGS['args']
            force = context.CLIARGS['force']
            output_path = context.CLIARGS['collections_path']
            # TODO: use a list of server that have been configured in ~/.ansible_galaxy
            servers = [context.CLIARGS['api_server']]
            ignore_certs = context.CLIARGS['ignore_certs']
            ignore_errors = context.CLIARGS['ignore_errors']
            requirements_file = context.CLIARGS['requirements']
            no_deps = context.CLIARGS['no_deps']
            force_deps = context.CLIARGS['force_with_deps']

            if collections and requirements_file:
                raise AnsibleError("The positional collection_name arg and --requirements-file are mutually exclusive.")
            elif not collections and not requirements_file:
                raise AnsibleError("You must specify a collection name or a requirements file.")

            if requirements_file:
                requirements_file = GalaxyCLI._resolve_path(requirements_file)
                collection_requirements = parse_collections_requirements_file(requirements_file)
            else:
                collection_requirements = []
                for collection_input in collections:
                    name, dummy, requirement = collection_input.partition(':')
                    collection_requirements.append((name, requirement or '*', None))

            output_path = GalaxyCLI._resolve_path(output_path)
            collections_path = C.COLLECTIONS_PATHS

            if len([p for p in collections_path if p.startswith(output_path)]) == 0:
                display.warning("The specified collections path '%s' is not part of the configured Ansible "
                                "collections paths '%s'. The installed collection won't be picked up in an Ansible "
                                "run." % (to_text(output_path), to_text(":".join(collections_path))))

            if os.path.split(output_path)[1] != 'ansible_collections':
                output_path = os.path.join(output_path, 'ansible_collections')

            b_output_path = to_bytes(output_path, errors='surrogate_or_strict')
            if not os.path.exists(b_output_path):
                os.makedirs(b_output_path)

            install_collections(collection_requirements, output_path, servers, (not ignore_certs), ignore_errors,
                                no_deps, force, force_deps)

            return 0

        role_file = context.CLIARGS['role_file']

        if not context.CLIARGS['args'] and role_file is None:
            # the user needs to specify one of either --role-file or specify a single user/role name
            raise AnsibleOptionsError("- you must specify a user/role name or a roles file")

        no_deps = context.CLIARGS['no_deps']
        force_deps = context.CLIARGS['force_with_deps']

        force = context.CLIARGS['force'] or force_deps

        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 AnsibleError(
                            "Unable to load data from the requirements file (%s): %s" % (role_file, to_native(e))
                        )

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

                    for role in required_roles:
                        if "include" not in role:
                            role = RoleRequirement.role_yaml_parse(role)
                            display.vvv("found role %s in yaml file" % str(role))
                            if "name" not in role and "scm" not in role:
                                raise AnsibleError("Must specify name or src for role")
                            roles_left.append(GalaxyRole(self.galaxy, **role))
                        else:
                            with open(role["include"]) as f_include:
                                try:
                                    roles_left += [
                                        GalaxyRole(self.galaxy, **r) for r in
                                        (RoleRequirement.role_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 AnsibleError(msg % (role_file, e))
                else:
                    raise AnsibleError("Invalid role requirements file")
                f.close()
            except (IOError, OSError) as e:
                raise AnsibleError('Unable to open %s: %s' % (role_file, to_native(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 context.CLIARGS['args']:
                role = RoleRequirement.role_yaml_parse(rname.strip())
                roles_left.append(GalaxyRole(self.galaxy, **role))

        for role in roles_left:
            # only process roles in roles files when names matches if given
            if role_file and context.CLIARGS['args'] and role.name not in context.CLIARGS['args']:
                display.vvv('Skipping role %s' % role.name)
                continue

            display.vvv('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:
                        display.display('- changing role %s from %s to %s' %
                                        (role.name, role.install_info['version'], role.version or "unspecified"))
                        role.remove()
                    else:
                        display.warning('- %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:
                        display.display('- %s is already installed, skipping.' % str(role))
                        continue

            try:
                installed = role.install()
            except AnsibleError as e:
                display.warning(u"- %s was NOT installed successfully: %s " % (role.name, to_text(e)))
                self.exit_without_ignore()
                continue

            # install dependencies, if we want them
            if not no_deps and installed:
                if not role.metadata:
                    display.warning("Meta file %s is empty. Skipping dependencies." % role.path)
                else:
                    role_dependencies = role.metadata.get('dependencies') or []
                    for dep in role_dependencies:
                        display.debug('Installing dep %s' % dep)
                        dep_req = RoleRequirement()
                        dep_info = dep_req.role_yaml_parse(dep)
                        dep_role = GalaxyRole(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:
                                display.display('- adding dependency: %s' % to_text(dep_role))
                                roles_left.append(dep_role)
                            else:
                                display.display('- dependency %s already pending installation.' % dep_role.name)
                        else:
                            if dep_role.install_info['version'] != dep_role.version:
                                if force_deps:
                                    display.display('- changing dependant role %s from %s to %s' %
                                                    (dep_role.name, dep_role.install_info['version'], dep_role.version or "unspecified"))
                                    dep_role.remove()
                                    roles_left.append(dep_role)
                                else:
                                    display.warning('- dependency %s (%s) from role %s differs from already installed version (%s), skipping' %
                                                    (to_text(dep_role), dep_role.version, role.name, dep_role.install_info['version']))
                            else:
                                if force_deps:
                                    roles_left.append(dep_role)
                                else:
                                    display.display('- dependency %s is already installed, skipping.' % dep_role.name)

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

        return 0
Exemple #33
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 AnsibleOptionsError("- 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 AnsibleError("Unable to load data from the requirements file: %s" % role_file)

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

                    for role in required_roles:
                        if "include" not in role:
                            role = RoleRequirement.role_yaml_parse(role)
                            display.vvv("found role %s in yaml file" % str(role))
                            if "name" not in role and "scm" not in role:
                                raise AnsibleError("Must specify name or src for role")
                            roles_left.append(GalaxyRole(self.galaxy, **role))
                        else:
                            with open(role["include"]) as f_include:
                                try:
                                    roles_left += [
                                        GalaxyRole(self.galaxy, **r) for r in
                                        (RoleRequirement.role_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 AnsibleError(msg % (role_file, e))
                else:
                    display.deprecated("going forward only the yaml format will be supported", version="2.6")
                    # roles listed in a file, one per line
                    for rline in f.readlines():
                        if rline.startswith("#") or rline.strip() == '':
                            continue
                        display.debug('found role %s in text file' % str(rline))
                        role = RoleRequirement.role_yaml_parse(rline.strip())
                        roles_left.append(GalaxyRole(self.galaxy, **role))
                f.close()
            except (IOError, OSError) as e:
                raise AnsibleError('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 = RoleRequirement.role_yaml_parse(rname.strip())
                roles_left.append(GalaxyRole(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:
                display.vvv('Skipping role %s' % role.name)
                continue

            display.vvv('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:
                        display.display('- changing role %s from %s to %s' %
                                        (role.name, role.install_info['version'], role.version or "unspecified"))
                        role.remove()
                    else:
                        display.warning('- %s (%s) is already installed - use --force to change version to %s' %
                                        (role.name, role.install_info['version'], role.version or "unspecified"))
                        continue
                else:
                    display.display('- %s is already installed, skipping.' % str(role))
                    continue

            try:
                installed = role.install()
            except AnsibleError as e:
                display.warning("- %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:
                    display.warning("Meta file %s is empty. Skipping dependencies." % role.path)
                else:
                    role_dependencies = role.metadata.get('dependencies') or []
                    for dep in role_dependencies:
                        display.debug('Installing dep %s' % dep)
                        dep_req = RoleRequirement()
                        dep_info = dep_req.role_yaml_parse(dep)
                        dep_role = GalaxyRole(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:
                                display.display('- adding dependency: %s' % str(dep_role))
                                roles_left.append(dep_role)
                            else:
                                display.display('- dependency %s already pending installation.' % dep_role.name)
                        else:
                            if dep_role.install_info['version'] != dep_role.version:
                                display.warning('- dependency %s from role %s differs from already installed version (%s), skipping' %
                                                (str(dep_role), role.name, dep_role.install_info['version']))
                            else:
                                display.display('- dependency %s is already installed, skipping.' % dep_role.name)

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

        return 0
Exemple #34
0
    def install(self):
        # the file is a tar, so open it that way and extract it
        # to the specified (or default) roles directory
        local_file = False

        if self.scm:
            # create tar file from scm url
            tmp_file = RoleRequirement.scm_archive_role(**self.spec)
        elif self.src:
            if os.path.isfile(self.src):
                # installing a local tar.gz
                local_file = True
                tmp_file = self.src
            elif '://' in self.src:
                role_data = self.src
                tmp_file = self.fetch(role_data)
            else:
                api = GalaxyAPI(self.galaxy)
                role_data = api.lookup_role_by_name(self.src)
                if not role_data:
                    raise AnsibleError("- sorry, %s was not found on %s." % (self.src, api.api_server))

                if role_data.get('role_type') == 'CON' and not os.environ.get('ANSIBLE_CONTAINER'):
                    # Container Enabled, running outside of a container
                    display.warning("%s is a Container Enabled role and should only be installed using "
                                    "Ansible Container" % self.name)

                if role_data.get('role_type') == 'APP':
                    # Container Role
                    display.warning("%s is a Container App role and should only be installed using Ansible "
                                    "Container" % self.name)

                role_versions = api.fetch_role_related('versions', role_data['id'])
                if not self.version:
                    # convert the version names to LooseVersion objects
                    # and sort them to get the latest version. If there
                    # are no versions in the list, we'll grab the head
                    # of the master branch
                    if len(role_versions) > 0:
                        loose_versions = [LooseVersion(a.get('name', None)) for a in role_versions]
                        loose_versions.sort()
                        self.version = str(loose_versions[-1])
                    elif role_data.get('github_branch', None):
                        self.version = role_data['github_branch']
                    else:
                        self.version = 'master'
                elif self.version != 'master':
                    if role_versions and str(self.version) not in [a.get('name', None) for a in role_versions]:
                        raise AnsibleError("- the specified version (%s) of %s was not found in the list of available versions (%s)." % (self.version,
                                                                                                                                         self.name,
                                                                                                                                         role_versions))

                tmp_file = self.fetch(role_data)

        else:
            raise AnsibleError("No valid role data found")

        if tmp_file:

            display.debug("installing from %s" % tmp_file)

            if not tarfile.is_tarfile(tmp_file):
                raise AnsibleError("the file downloaded was not a tar.gz")
            else:
                if tmp_file.endswith('.gz'):
                    role_tar_file = tarfile.open(tmp_file, "r:gz")
                else:
                    role_tar_file = tarfile.open(tmp_file, "r")
                # verify the role's meta file
                meta_file = None
                members = role_tar_file.getmembers()
                # next find the metadata file
                for member in members:
                    if self.META_MAIN in member.name:
                        # Look for parent of meta/main.yml
                        # Due to possibility of sub roles each containing meta/main.yml
                        # look for shortest length parent
                        meta_parent_dir = os.path.dirname(os.path.dirname(member.name))
                        if not meta_file:
                            archive_parent_dir = meta_parent_dir
                            meta_file = member
                        else:
                            if len(meta_parent_dir) < len(archive_parent_dir):
                                archive_parent_dir = meta_parent_dir
                                meta_file = member
                if not meta_file:
                    raise AnsibleError("this role does not appear to have a meta/main.yml file.")
                else:
                    try:
                        self._metadata = yaml.safe_load(role_tar_file.extractfile(meta_file))
                    except:
                        raise AnsibleError("this role does not appear to have a valid meta/main.yml file.")

                # we strip off any higher-level directories for all of the files contained within
                # the tar file here. The default is 'github_repo-target'. Gerrit instances, on the other
                # hand, does not have a parent directory at all.
                installed = False
                while not installed:
                    display.display("- extracting %s to %s" % (self.name, self.path))
                    try:
                        if os.path.exists(self.path):
                            if not os.path.isdir(self.path):
                                raise AnsibleError("the specified roles path exists and is not a directory.")
                            elif not getattr(self.options, "force", False):
                                raise AnsibleError("the specified role %s appears to already exist. Use --force to replace it." % self.name)
                            else:
                                # using --force, remove the old path
                                if not self.remove():
                                    raise AnsibleError("%s doesn't appear to contain a role.\n  please remove this directory manually if you really "
                                                       "want to put the role here." % self.path)
                        else:
                            os.makedirs(self.path)

                        # now we do the actual extraction to the path
                        for member in members:
                            # we only extract files, and remove any relative path
                            # bits that might be in the file for security purposes
                            # and drop any containing directory, as mentioned above
                            if member.isreg() or member.issym():
                                parts = member.name.replace(archive_parent_dir, "", 1).split(os.sep)
                                final_parts = []
                                for part in parts:
                                    if part != '..' and '~' not in part and '$' not in part:
                                        final_parts.append(part)
                                member.name = os.path.join(*final_parts)
                                role_tar_file.extract(member, self.path)

                        # write out the install info file for later use
                        self._write_galaxy_install_info()
                        installed = True
                    except OSError as e:
                        error = True
                        if e[0] == 13 and len(self.paths) > 1:
                            current = self.paths.index(self.path)
                            nextidx = current + 1
                            if len(self.paths) >= current:
                                self.path = self.paths[nextidx]
                                error = False
                        if error:
                            raise AnsibleError("Could not update files in %s: %s" % (self.path, str(e)))

                # return the parsed yaml metadata
                display.display("- %s was installed successfully" % str(self))
                if not local_file:
                    try:
                        os.unlink(tmp_file)
                    except (OSError, IOError) as e:
                        display.warning("Unable to remove tmp file (%s): %s" % (tmp_file, str(e)))
                return True

        return False
Exemple #35
0
    def execute_install(self):
        """
        Executes the installation action. The args list contains the
        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.get_opt("role_file", None)

        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 AnsibleOptionsError(
                "- you must specify a user/role name or a roles file")
        elif len(self.args) == 1 and not role_file is None:
            # using a role file is mutually exclusive of specifying
            # the role name on the command line
            raise AnsibleOptionsError(
                "- please specify a user/role name, or a roles file, but not both"
            )

        no_deps = self.get_opt("no_deps", False)
        force = self.get_opt('force', False)

        roles_left = []
        if role_file:
            try:
                f = open(role_file, 'r')
                if role_file.endswith('.yaml') or role_file.endswith('.yml'):
                    for role in yaml.safe_load(f.read()):
                        role = RoleRequirement.role_yaml_parse(role)
                        self.display.debug('found role %s in yaml file' %
                                           str(role))
                        if 'name' not in role and 'scm' not in role:
                            raise AnsibleError(
                                "Must specify name or src for role")
                        roles_left.append(GalaxyRole(self.galaxy, **role))
                else:
                    self.display.deprecated(
                        "going forward only the yaml format will be supported")
                    # roles listed in a file, one per line
                    for rline in f.readlines():
                        self.display.debug('found role %s in text file' %
                                           str(rline))
                        role = RoleRequirement.role_yaml_parse(rline.strip())
                        roles_left.append(GalaxyRole(self.galaxy, **role))
                f.close()
            except (IOError, OSError) as e:
                self.display.error('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:
                roles_left.append(GalaxyRole(self.galaxy, rname.strip()))

        for role in roles_left:
            self.display.debug('Installing role %s ' % role.name)
            # query the galaxy API for the role data
            role_data = None

            if role.install_info is not None and not force:
                self.display.display('- %s is already installed, skipping.' %
                                     role.name)
                continue

            try:
                installed = role.install()
            except AnsibleError as e:
                self.display.warning(
                    "- %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:
                role_dependencies = role.metadata.get('dependencies', [])
                for dep in role_dependencies:
                    self.display.debug('Installing dep %s' % dep)
                    dep_req = RoleRequirement()
                    dep_info = dep_req.role_yaml_parse(dep)
                    dep_role = GalaxyRole(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 or force:
                        if dep_role not in roles_left:
                            self.display.display('- adding dependency: %s' %
                                                 dep_role.name)
                            roles_left.append(dep_role)
                        else:
                            self.display.display(
                                '- dependency %s already pending installation.'
                                % dep_role.name)
                    else:
                        self.display.display(
                            '- dependency %s is already installed, skipping.' %
                            dep_role.name)

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

        return 0
Exemple #36
0
def test_https_role_url():
    role = RoleRequirement.role_yaml_parse('https://github.com/bennojoy/nginx')
    assert role['src'] == 'https://github.com/bennojoy/nginx'
    assert role['name'] == 'nginx'
    assert role['scm'] is None
    assert role['version'] is None