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)
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)
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
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'
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
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)
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)
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)
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)
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
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 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
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
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
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
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
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
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
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
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
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
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
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
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