def fetch_role(playbook_path, role_name): options = Options() options.roles_path = '{playbook_path}/provision/roles'.format( playbook_path=playbook_path, ) if not path.exists(options.roles_path): makedirs(options.roles_path) galaxy = Galaxy(options) role = GalaxyRole(galaxy, role_name, path=options.roles_path) role.install() dependencies = get_application_dependencies( playbook_path, role_name, ) for role in dependencies: fetch_role(playbook_path, role)
def parse_requirements_files(self, role): if 'role' in role: # Old style: {role: "galaxy.role,version,name", other_vars: "here" } role_info = role_spec_parse(role['role']) if isinstance(role_info, dict): # Warning: Slight change in behaviour here. name may be being # overloaded. Previously, name was only a parameter to the role. # Now it is both a parameter to the role and the name that # ansible-galaxy will install under on the local system. if 'name' in role and 'name' in role_info: del role_info['name'] role.update(role_info) else: # New style: { src: 'galaxy.role,version,name', other_vars: "here" } if 'github.com' in role["src"] and 'http' in role["src"] and '+' not in role["src"] and not role["src"].endswith('.tar.gz'): role["src"] = "git+" + role["src"] if '+' in role["src"]: (scm, src) = role["src"].split('+') role["scm"] = scm role["src"] = src if 'name' not in role: role["name"] = GalaxyRole.url_to_spec(role["src"]) if 'version' not in role: role['version'] = '' if 'scm' not in role: role['scm'] = None return role
def execute_remove(self): """ removes the list of roles passed as arguments from the local system. """ if len(self.args) == 0: raise AnsibleOptionsError('- you must specify at least one role to remove.') for role_name in self.args: role = GalaxyRole(self.galaxy, role_name) try: if role.remove(): display.display('- successfully removed %s' % role_name) else: display.display('- %s is not installed, skipping.' % role_name) except Exception as e: raise AnsibleError("Failed to remove role %s: %s" % (role_name, str(e))) return 0
def execute_remove(self): """ Executes the remove action. The args list contains the list of roles to be removed. This list can contain more than one role. """ if len(self.args) == 0: raise AnsibleOptionsError('- you must specify at least one role to remove.') for role_name in self.args: role = GalaxyRole(self.galaxy, role_name) try: if role.remove(): display.display('- successfully removed %s' % role_name) else: display.display('- %s is not installed, skipping.' % role_name) except Exception as e: raise AnsibleError("Failed to remove role %s: %s" % (role_name, str(e))) return 0
def execute_remove(self): """ Executes the remove action. The args list contains the list of roles to be removed. This list can contain more than one role. """ if len(self.args) == 0: raise AnsibleOptionsError( '- you must specify at least one role to remove.') for role_name in self.args: role = GalaxyRole(self.galaxy, role_name) try: if role.remove(): self.display.display('- successfully removed %s' % role_name) else: self.display.display('- %s is not installed, skipping.' % role_name) except Exception as e: raise AnsibleError("Failed to remove role %s: %s" % (role_name, str(e))) return 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)
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)
def execute_list(self): """ Executes the list action. The args list can contain zero or one role. If one is specified, only that role will be shown, otherwise all roles in the specified directory will be shown. """ if len(self.args) > 1: raise AnsibleOptionsError("- please specify only one role to list, or specify no roles to see a full list") if len(self.args) == 1: # show only the request role, if it exists gr = GalaxyRole(self.galaxy, self.name) if gr.metadata: install_info = gr.install_info version = None if install_info: version = install_info.get("version", None) if not version: version = "(unknown version)" # show some more info about single roles here self.display.display("- %s, %s" % (self.name, version)) else: self.display.display("- the role %s was not found" % self.name) else: # show all valid roles in the roles_path directory roles_path = self.get_opt('roles_path') roles_path = os.path.expanduser(roles_path) if not os.path.exists(roles_path): raise AnsibleOptionsError("- the path %s does not exist. Please specify a valid path with --roles-path" % roles_path) elif not os.path.isdir(roles_path): raise AnsibleOptionsError("- %s exists, but it is not a directory. Please specify a valid path with --roles-path" % roles_path) path_files = os.listdir(roles_path) for path_file in path_files: if gr.metadata: install_info = gr.metadata version = None if install_info: version = install_info.get("version", None) if not version: version = "(unknown version)" self.display.display("- %s, %s" % (path_file, version)) return 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 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 _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 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.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 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 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
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) roles_path = self.get_opt("roles_path") roles_done = [] roles_left = [] role_name = self.args.pop(0).strip() gr = GalaxyRole(self.galaxy, role_name) if role_file: f = open(role_file, 'r') if role_file.endswith('.yaml') or role_file.endswith('.yml'): roles_left = map(ansible.utils.role_yaml_parse, yaml.safe_load(f)) else: # roles listed in a file, one per line for rname in f.readlines(): roles_left.append(GalaxyRole(self.galaxy, rname)) f.close() 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)) while len(roles_left) > 0: # query the galaxy API for the role data role_data = None role = roles_left.pop(0) role_src = role.src role_scm = role.scm role_path = role.path if role_path: self.options.roles_path = role_path else: self.options.roles_path = roles_path tmp_file = None 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 = scm_archive_role(role_scm, role_src, role.version, role.name) if role_src: if '://' in role_src: # just download a URL - version will probably be in the URL tmp_file = gr.fetch() else: 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 = gr.fetch(role_data) installed = False if tmp_file: installed = install_role(role.name, role.version, tmp_file, options) # 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 # this should use new roledepenencies code #if not no_deps and installed: # if not role_data: # role_data = gr.get_metadata(role.get("name"), options) # role_dependencies = role_data['dependencies'] # else: # role_dependencies = role_data['summary_fields']['dependencies'] # api_fetch_role_related(api_server, 'dependencies', role_data['id']) # for dep in role_dependencies: # if isinstance(dep, basestring): # dep = ansible.utils.role_spec_parse(dep) # else: # dep = ansible.utils.role_yaml_parse(dep) # if not get_role_metadata(dep["name"], options): # if dep not in roles_left: # print '- adding dependency: %s' % dep["name"] # roles_left.append(dep) # else: # print '- dependency %s already pending installation.' % dep["name"] # else: # print '- 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