Fix galaxy install dep failure
Also fixes issue where force does not force reinstall of deps Fixes #10425
This commit is contained in:
parent
1a39e32a13
commit
2a50957ad8
4 changed files with 126 additions and 106 deletions
|
@ -352,6 +352,7 @@ class GalaxyCLI(CLI):
|
|||
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 = []
|
||||
|
@ -389,6 +390,9 @@ class GalaxyCLI(CLI):
|
|||
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
|
||||
|
@ -443,25 +447,20 @@ class GalaxyCLI(CLI):
|
|||
os.unlink(tmp_file)
|
||||
# install dependencies, if we want them
|
||||
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'])
|
||||
role_dependencies = role.metadata.get('dependencies', [])
|
||||
for dep in role_dependencies:
|
||||
self.display.debug('Installing dep %s' % dep)
|
||||
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:
|
||||
self.display.display('- adding dependency: %s' % dep["name"])
|
||||
roles_left.append(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"])
|
||||
self.display.display('- dependency %s already pending installation.' % dep_name)
|
||||
else:
|
||||
self.display.display('- dependency %s is already installed, skipping.' % dep["name"])
|
||||
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)
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
import os
|
||||
|
||||
from six import string_types
|
||||
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.utils.display import Display
|
||||
|
||||
|
@ -40,9 +42,9 @@ class Galaxy(object):
|
|||
self.display = display
|
||||
|
||||
self.options = options
|
||||
self.roles_path = getattr(self.options, 'roles_path', None)
|
||||
if self.roles_path:
|
||||
self.roles_path = os.path.expanduser(self.roles_path)
|
||||
roles_paths = getattr(self.options, 'roles_path', [])
|
||||
if isinstance(roles_paths, string_types):
|
||||
self.roles_paths = [os.path.expanduser(roles_path) for roles_path in roles_paths.split(os.pathsep)]
|
||||
|
||||
self.roles = {}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ class GalaxyRole(object):
|
|||
ROLE_DIRS = ('defaults','files','handlers','meta','tasks','templates','vars')
|
||||
|
||||
|
||||
def __init__(self, galaxy, name, src=None, version=None, scm=None):
|
||||
def __init__(self, galaxy, name, src=None, version=None, scm=None, role_path=None):
|
||||
|
||||
self._metadata = None
|
||||
self._install_info = None
|
||||
|
@ -52,7 +52,20 @@ class GalaxyRole(object):
|
|||
self.src = src or name
|
||||
self.scm = scm
|
||||
|
||||
self.path = (os.path.join(galaxy.roles_path, self.name))
|
||||
if role_path is not None:
|
||||
self.path = role_path
|
||||
else:
|
||||
for path in galaxy.roles_paths:
|
||||
role_path = os.path.join(path, self.name)
|
||||
if os.path.exists(role_path):
|
||||
self.path = role_path
|
||||
break
|
||||
else:
|
||||
# use the first path by default
|
||||
self.path = os.path.join(galaxy.roles_paths[0], self.name)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.name == other.name
|
||||
|
||||
def fetch_from_scm_archive(self):
|
||||
|
||||
|
|
|
@ -54,26 +54,26 @@ class RoleRequirement(RoleDefinition):
|
|||
|
||||
assert type(ds) == dict or isinstance(ds, string_types)
|
||||
|
||||
role_name = ''
|
||||
role_name = None
|
||||
role_params = dict()
|
||||
new_ds = dict()
|
||||
|
||||
if isinstance(ds, string_types):
|
||||
role_name = ds
|
||||
else:
|
||||
ds = self._preprocess_role_spec(ds)
|
||||
(new_ds, role_params) = self._split_role_params(ds)
|
||||
(new_ds, role_params) = self._split_role_params(self._preprocess_role_spec(ds))
|
||||
|
||||
# pull the role name out of the ds
|
||||
role_name = new_ds.get('role_name')
|
||||
del ds['role_name']
|
||||
role_name = new_ds.pop('role_name', new_ds.pop('role', None))
|
||||
|
||||
if role_name is None:
|
||||
raise AnsibleError("Role requirement did not contain a role name!", obj=ds)
|
||||
return (new_ds, role_name, role_params)
|
||||
|
||||
def _preprocess_role_spec(self, ds):
|
||||
if 'role' in ds:
|
||||
# Old style: {role: "galaxy.role,version,name", other_vars: "here" }
|
||||
role_info = self._role_spec_parse(ds['role'])
|
||||
role_info = role_spec_parse(ds['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.
|
||||
|
@ -96,7 +96,7 @@ class RoleRequirement(RoleDefinition):
|
|||
ds["role"] = ds["name"]
|
||||
del ds["name"]
|
||||
else:
|
||||
ds["role"] = self._repo_url_to_role_name(ds["src"])
|
||||
ds["role"] = repo_url_to_role_name(ds["src"])
|
||||
|
||||
# set some values to a default value, if none were specified
|
||||
ds.setdefault('version', '')
|
||||
|
@ -104,96 +104,102 @@ class RoleRequirement(RoleDefinition):
|
|||
|
||||
return ds
|
||||
|
||||
def _repo_url_to_role_name(self, repo_url):
|
||||
# gets the role name out of a repo like
|
||||
# http://git.example.com/repos/repo.git" => "repo"
|
||||
def repo_url_to_role_name(repo_url):
|
||||
# gets the role name out of a repo like
|
||||
# http://git.example.com/repos/repo.git" => "repo"
|
||||
|
||||
if '://' not in repo_url and '@' not in repo_url:
|
||||
return repo_url
|
||||
trailing_path = repo_url.split('/')[-1]
|
||||
if trailing_path.endswith('.git'):
|
||||
trailing_path = trailing_path[:-4]
|
||||
if trailing_path.endswith('.tar.gz'):
|
||||
trailing_path = trailing_path[:-7]
|
||||
if ',' in trailing_path:
|
||||
trailing_path = trailing_path.split(',')[0]
|
||||
return trailing_path
|
||||
if '://' not in repo_url and '@' not in repo_url:
|
||||
return repo_url
|
||||
trailing_path = repo_url.split('/')[-1]
|
||||
if trailing_path.endswith('.git'):
|
||||
trailing_path = trailing_path[:-4]
|
||||
if trailing_path.endswith('.tar.gz'):
|
||||
trailing_path = trailing_path[:-7]
|
||||
if ',' in trailing_path:
|
||||
trailing_path = trailing_path.split(',')[0]
|
||||
return trailing_path
|
||||
|
||||
def _role_spec_parse(self, role_spec):
|
||||
# takes a repo and a version like
|
||||
# git+http://git.example.com/repos/repo.git,v1.0
|
||||
# and returns a list of properties such as:
|
||||
# {
|
||||
# 'scm': 'git',
|
||||
# 'src': 'http://git.example.com/repos/repo.git',
|
||||
# 'version': 'v1.0',
|
||||
# 'name': 'repo'
|
||||
# }
|
||||
def role_spec_parse(role_spec):
|
||||
# takes a repo and a version like
|
||||
# git+http://git.example.com/repos/repo.git,v1.0
|
||||
# and returns a list of properties such as:
|
||||
# {
|
||||
# 'scm': 'git',
|
||||
# 'src': 'http://git.example.com/repos/repo.git',
|
||||
# 'version': 'v1.0',
|
||||
# 'name': 'repo'
|
||||
# }
|
||||
|
||||
default_role_versions = dict(git='master', hg='tip')
|
||||
default_role_versions = dict(git='master', hg='tip')
|
||||
|
||||
role_spec = role_spec.strip()
|
||||
role_version = ''
|
||||
if role_spec == "" or role_spec.startswith("#"):
|
||||
return (None, None, None, None)
|
||||
role_spec = role_spec.strip()
|
||||
role_version = ''
|
||||
if role_spec == "" or role_spec.startswith("#"):
|
||||
return (None, None, None, None)
|
||||
|
||||
tokens = [s.strip() for s in role_spec.split(',')]
|
||||
tokens = [s.strip() for s in role_spec.split(',')]
|
||||
|
||||
# assume https://github.com URLs are git+https:// URLs and not
|
||||
# tarballs unless they end in '.zip'
|
||||
if 'github.com/' in tokens[0] and not tokens[0].startswith("git+") and not tokens[0].endswith('.tar.gz'):
|
||||
tokens[0] = 'git+' + tokens[0]
|
||||
# assume https://github.com URLs are git+https:// URLs and not
|
||||
# tarballs unless they end in '.zip'
|
||||
if 'github.com/' in tokens[0] and not tokens[0].startswith("git+") and not tokens[0].endswith('.tar.gz'):
|
||||
tokens[0] = 'git+' + tokens[0]
|
||||
|
||||
if '+' in tokens[0]:
|
||||
(scm, role_url) = tokens[0].split('+')
|
||||
else:
|
||||
scm = None
|
||||
role_url = tokens[0]
|
||||
|
||||
if len(tokens) >= 2:
|
||||
role_version = tokens[1]
|
||||
|
||||
if len(tokens) == 3:
|
||||
role_name = tokens[2]
|
||||
else:
|
||||
role_name = self._repo_url_to_role_name(tokens[0])
|
||||
|
||||
if scm and not role_version:
|
||||
role_version = default_role_versions.get(scm, '')
|
||||
|
||||
return dict(scm=scm, src=role_url, version=role_version, role_name=role_name)
|
||||
|
||||
|
||||
def role_yaml_parse(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)
|
||||
if '+' in tokens[0]:
|
||||
(scm, role_url) = tokens[0].split('+')
|
||||
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"]
|
||||
scm = None
|
||||
role_url = tokens[0]
|
||||
|
||||
if '+' in role["src"]:
|
||||
(scm, src) = role["src"].split('+')
|
||||
role["scm"] = scm
|
||||
role["src"] = src
|
||||
if len(tokens) >= 2:
|
||||
role_version = tokens[1]
|
||||
|
||||
if 'name' not in role:
|
||||
role["name"] = repo_url_to_role_name(role["src"])
|
||||
if len(tokens) == 3:
|
||||
role_name = tokens[2]
|
||||
else:
|
||||
role_name = repo_url_to_role_name(tokens[0])
|
||||
|
||||
if 'version' not in role:
|
||||
role['version'] = ''
|
||||
if scm and not role_version:
|
||||
role_version = default_role_versions.get(scm, '')
|
||||
|
||||
if 'scm' not in role:
|
||||
role['scm'] = None
|
||||
return dict(scm=scm, src=role_url, version=role_version, role_name=role_name)
|
||||
|
||||
return role
|
||||
# FIXME: all of these methods need to be cleaned up/reorganized below this
|
||||
def get_opt(options, k, defval=""):
|
||||
"""
|
||||
Returns an option from an Optparse values instance.
|
||||
"""
|
||||
try:
|
||||
data = getattr(options, k)
|
||||
except:
|
||||
return defval
|
||||
if k == "roles_path":
|
||||
if os.pathsep in data:
|
||||
data = data.split(os.pathsep)[0]
|
||||
return data
|
||||
|
||||
def get_role_path(role_name, options):
|
||||
"""
|
||||
Returns the role path based on the roles_path option
|
||||
and the role name.
|
||||
"""
|
||||
roles_path = get_opt(options,'roles_path')
|
||||
roles_path = os.path.join(roles_path, role_name)
|
||||
roles_path = os.path.expanduser(roles_path)
|
||||
return roles_path
|
||||
|
||||
def get_role_metadata(role_name, options):
|
||||
"""
|
||||
Returns the metadata as YAML, if the file 'meta/main.yml'
|
||||
exists in the specified role_path
|
||||
"""
|
||||
role_path = os.path.join(get_role_path(role_name, options), 'meta/main.yml')
|
||||
try:
|
||||
if os.path.isfile(role_path):
|
||||
f = open(role_path, 'r')
|
||||
meta_data = yaml.safe_load(f)
|
||||
f.close()
|
||||
return meta_data
|
||||
else:
|
||||
return None
|
||||
except:
|
||||
return None
|
||||
|
|
Loading…
Reference in a new issue