|
|
@ -28,7 +28,6 @@ import sys
|
|
|
|
import yaml
|
|
|
|
import yaml
|
|
|
|
|
|
|
|
|
|
|
|
from collections import defaultdict
|
|
|
|
from collections import defaultdict
|
|
|
|
from distutils.version import LooseVersion
|
|
|
|
|
|
|
|
from jinja2 import Environment
|
|
|
|
from jinja2 import Environment
|
|
|
|
|
|
|
|
|
|
|
|
import ansible.constants as C
|
|
|
|
import ansible.constants as C
|
|
|
@ -39,16 +38,24 @@ from ansible.galaxy.api import GalaxyAPI
|
|
|
|
from ansible.galaxy.role import GalaxyRole
|
|
|
|
from ansible.galaxy.role import GalaxyRole
|
|
|
|
from ansible.playbook.role.requirement import RoleRequirement
|
|
|
|
from ansible.playbook.role.requirement import RoleRequirement
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
from __main__ import display
|
|
|
|
|
|
|
|
display = display
|
|
|
|
|
|
|
|
except ImportError:
|
|
|
|
|
|
|
|
from ansible.utils.display import Display
|
|
|
|
|
|
|
|
display = Display()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GalaxyCLI(CLI):
|
|
|
|
class GalaxyCLI(CLI):
|
|
|
|
|
|
|
|
|
|
|
|
VALID_ACTIONS = ("init", "info", "install", "list", "remove", "search")
|
|
|
|
VALID_ACTIONS = ("init", "info", "install", "list", "remove", "search")
|
|
|
|
SKIP_INFO_KEYS = ("name", "description", "readme_html", "related", "summary_fields", "average_aw_composite", "average_aw_score", "url" )
|
|
|
|
SKIP_INFO_KEYS = ("name", "description", "readme_html", "related", "summary_fields", "average_aw_composite", "average_aw_score", "url" )
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, args, display=None):
|
|
|
|
def __init__(self, args):
|
|
|
|
|
|
|
|
|
|
|
|
self.api = None
|
|
|
|
self.api = None
|
|
|
|
self.galaxy = None
|
|
|
|
self.galaxy = None
|
|
|
|
super(GalaxyCLI, self).__init__(args, display)
|
|
|
|
super(GalaxyCLI, self).__init__(args)
|
|
|
|
|
|
|
|
|
|
|
|
def parse(self):
|
|
|
|
def parse(self):
|
|
|
|
''' create an options parser for bin/ansible '''
|
|
|
|
''' create an options parser for bin/ansible '''
|
|
|
@ -58,7 +65,6 @@ class GalaxyCLI(CLI):
|
|
|
|
epilog = "\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0])
|
|
|
|
epilog = "\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0])
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.set_action()
|
|
|
|
self.set_action()
|
|
|
|
|
|
|
|
|
|
|
|
# options specific to actions
|
|
|
|
# options specific to actions
|
|
|
@ -109,8 +115,8 @@ class GalaxyCLI(CLI):
|
|
|
|
|
|
|
|
|
|
|
|
# get options, args and galaxy object
|
|
|
|
# get options, args and galaxy object
|
|
|
|
self.options, self.args =self.parser.parse_args()
|
|
|
|
self.options, self.args =self.parser.parse_args()
|
|
|
|
self.display.verbosity = self.options.verbosity
|
|
|
|
display.verbosity = self.options.verbosity
|
|
|
|
self.galaxy = Galaxy(self.options, self.display)
|
|
|
|
self.galaxy = Galaxy(self.options)
|
|
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
@ -178,10 +184,10 @@ class GalaxyCLI(CLI):
|
|
|
|
if os.path.isfile(role_path):
|
|
|
|
if os.path.isfile(role_path):
|
|
|
|
raise AnsibleError("- the path %s already exists, but is a file - aborting" % role_path)
|
|
|
|
raise AnsibleError("- the path %s already exists, but is a file - aborting" % role_path)
|
|
|
|
elif not force:
|
|
|
|
elif not force:
|
|
|
|
raise AnsibleError("- the directory %s already exists." % role_path + \
|
|
|
|
raise AnsibleError("- the directory %s already exists."
|
|
|
|
"you can use --force to re-initialize this directory,\n" + \
|
|
|
|
"you can use --force to re-initialize this directory,\n"
|
|
|
|
"however it will reset any main.yml files that may have\n" + \
|
|
|
|
"however it will reset any main.yml files that may have\n"
|
|
|
|
"been modified there already.")
|
|
|
|
"been modified there already." % role_path)
|
|
|
|
|
|
|
|
|
|
|
|
# create the default README.md
|
|
|
|
# create the default README.md
|
|
|
|
if not os.path.exists(role_path):
|
|
|
|
if not os.path.exists(role_path):
|
|
|
@ -234,7 +240,7 @@ class GalaxyCLI(CLI):
|
|
|
|
f = open(main_yml_path, 'w')
|
|
|
|
f = open(main_yml_path, 'w')
|
|
|
|
f.write('---\n# %s file for %s\n' % (dir,role_name))
|
|
|
|
f.write('---\n# %s file for %s\n' % (dir,role_name))
|
|
|
|
f.close()
|
|
|
|
f.close()
|
|
|
|
self.display.display("- %s was created successfully" % role_name)
|
|
|
|
display.display("- %s was created successfully" % role_name)
|
|
|
|
|
|
|
|
|
|
|
|
def execute_info(self):
|
|
|
|
def execute_info(self):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
@ -297,7 +303,7 @@ class GalaxyCLI(CLI):
|
|
|
|
# the user needs to specify one of either --role-file
|
|
|
|
# the user needs to specify one of either --role-file
|
|
|
|
# or specify a single user/role name
|
|
|
|
# or specify a single user/role name
|
|
|
|
raise AnsibleOptionsError("- you must specify a user/role name or a roles file")
|
|
|
|
raise AnsibleOptionsError("- you must specify a user/role name or a roles file")
|
|
|
|
elif len(self.args) == 1 and not role_file is None:
|
|
|
|
elif len(self.args) == 1 and role_file is not None:
|
|
|
|
# using a role file is mutually exclusive of specifying
|
|
|
|
# using a role file is mutually exclusive of specifying
|
|
|
|
# the role name on the command line
|
|
|
|
# the role name on the command line
|
|
|
|
raise AnsibleOptionsError("- please specify a user/role name, or a roles file, but not both")
|
|
|
|
raise AnsibleOptionsError("- please specify a user/role name, or a roles file, but not both")
|
|
|
@ -320,22 +326,22 @@ class GalaxyCLI(CLI):
|
|
|
|
|
|
|
|
|
|
|
|
for role in required_roles:
|
|
|
|
for role in required_roles:
|
|
|
|
role = RoleRequirement.role_yaml_parse(role)
|
|
|
|
role = RoleRequirement.role_yaml_parse(role)
|
|
|
|
self.display.debug('found role %s in yaml file' % str(role))
|
|
|
|
display.debug('found role %s in yaml file' % str(role))
|
|
|
|
if 'name' not in role and 'scm' not in role:
|
|
|
|
if 'name' not in role and 'scm' not in role:
|
|
|
|
raise AnsibleError("Must specify name or src for role")
|
|
|
|
raise AnsibleError("Must specify name or src for role")
|
|
|
|
roles_left.append(GalaxyRole(self.galaxy, **role))
|
|
|
|
roles_left.append(GalaxyRole(self.galaxy, **role))
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
self.display.deprecated("going forward only the yaml format will be supported")
|
|
|
|
display.deprecated("going forward only the yaml format will be supported")
|
|
|
|
# roles listed in a file, one per line
|
|
|
|
# roles listed in a file, one per line
|
|
|
|
for rline in f.readlines():
|
|
|
|
for rline in f.readlines():
|
|
|
|
if rline.startswith("#") or rline.strip() == '':
|
|
|
|
if rline.startswith("#") or rline.strip() == '':
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
self.display.debug('found role %s in text file' % str(rline))
|
|
|
|
display.debug('found role %s in text file' % str(rline))
|
|
|
|
role = RoleRequirement.role_yaml_parse(rline.strip())
|
|
|
|
role = RoleRequirement.role_yaml_parse(rline.strip())
|
|
|
|
roles_left.append(GalaxyRole(self.galaxy, **role))
|
|
|
|
roles_left.append(GalaxyRole(self.galaxy, **role))
|
|
|
|
f.close()
|
|
|
|
f.close()
|
|
|
|
except (IOError, OSError) as e:
|
|
|
|
except (IOError, OSError) as e:
|
|
|
|
self.display.error('Unable to open %s: %s' % (role_file, str(e)))
|
|
|
|
display.error('Unable to open %s: %s' % (role_file, str(e)))
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
# roles were specified directly, so we'll just go out grab them
|
|
|
|
# roles were specified directly, so we'll just go out grab them
|
|
|
|
# (and their dependencies, unless the user doesn't want us to).
|
|
|
|
# (and their dependencies, unless the user doesn't want us to).
|
|
|
@ -343,18 +349,17 @@ class GalaxyCLI(CLI):
|
|
|
|
roles_left.append(GalaxyRole(self.galaxy, rname.strip()))
|
|
|
|
roles_left.append(GalaxyRole(self.galaxy, rname.strip()))
|
|
|
|
|
|
|
|
|
|
|
|
for role in roles_left:
|
|
|
|
for role in roles_left:
|
|
|
|
self.display.debug('Installing role %s ' % role.name)
|
|
|
|
display.debug('Installing role %s ' % role.name)
|
|
|
|
# query the galaxy API for the role data
|
|
|
|
# query the galaxy API for the role data
|
|
|
|
role_data = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if role.install_info is not None and not force:
|
|
|
|
if role.install_info is not None and not force:
|
|
|
|
self.display.display('- %s is already installed, skipping.' % role.name)
|
|
|
|
display.display('- %s is already installed, skipping.' % role.name)
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
installed = role.install()
|
|
|
|
installed = role.install()
|
|
|
|
except AnsibleError as e:
|
|
|
|
except AnsibleError as e:
|
|
|
|
self.display.warning("- %s was NOT installed successfully: %s " % (role.name, str(e)))
|
|
|
|
display.warning("- %s was NOT installed successfully: %s " % (role.name, str(e)))
|
|
|
|
self.exit_without_ignore()
|
|
|
|
self.exit_without_ignore()
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
@ -362,7 +367,7 @@ class GalaxyCLI(CLI):
|
|
|
|
if not no_deps and installed:
|
|
|
|
if not no_deps and installed:
|
|
|
|
role_dependencies = role.metadata.get('dependencies') or []
|
|
|
|
role_dependencies = role.metadata.get('dependencies') or []
|
|
|
|
for dep in role_dependencies:
|
|
|
|
for dep in role_dependencies:
|
|
|
|
self.display.debug('Installing dep %s' % dep)
|
|
|
|
display.debug('Installing dep %s' % dep)
|
|
|
|
dep_req = RoleRequirement()
|
|
|
|
dep_req = RoleRequirement()
|
|
|
|
dep_info = dep_req.role_yaml_parse(dep)
|
|
|
|
dep_info = dep_req.role_yaml_parse(dep)
|
|
|
|
dep_role = GalaxyRole(self.galaxy, **dep_info)
|
|
|
|
dep_role = GalaxyRole(self.galaxy, **dep_info)
|
|
|
@ -372,15 +377,15 @@ class GalaxyCLI(CLI):
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
if dep_role.install_info is None or force:
|
|
|
|
if dep_role.install_info is None or force:
|
|
|
|
if dep_role not in roles_left:
|
|
|
|
if dep_role not in roles_left:
|
|
|
|
self.display.display('- adding dependency: %s' % dep_role.name)
|
|
|
|
display.display('- adding dependency: %s' % dep_role.name)
|
|
|
|
roles_left.append(dep_role)
|
|
|
|
roles_left.append(dep_role)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
self.display.display('- dependency %s already pending installation.' % dep_role.name)
|
|
|
|
display.display('- dependency %s already pending installation.' % dep_role.name)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
self.display.display('- dependency %s is already installed, skipping.' % dep_role.name)
|
|
|
|
display.display('- dependency %s is already installed, skipping.' % dep_role.name)
|
|
|
|
|
|
|
|
|
|
|
|
if not installed:
|
|
|
|
if not installed:
|
|
|
|
self.display.warning("- %s was NOT installed successfully." % role.name)
|
|
|
|
display.warning("- %s was NOT installed successfully." % role.name)
|
|
|
|
self.exit_without_ignore()
|
|
|
|
self.exit_without_ignore()
|
|
|
|
|
|
|
|
|
|
|
|
return 0
|
|
|
|
return 0
|
|
|
@ -398,9 +403,9 @@ class GalaxyCLI(CLI):
|
|
|
|
role = GalaxyRole(self.galaxy, role_name)
|
|
|
|
role = GalaxyRole(self.galaxy, role_name)
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
if role.remove():
|
|
|
|
if role.remove():
|
|
|
|
self.display.display('- successfully removed %s' % role_name)
|
|
|
|
display.display('- successfully removed %s' % role_name)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
self.display.display('- %s is not installed, skipping.' % role_name)
|
|
|
|
display.display('- %s is not installed, skipping.' % role_name)
|
|
|
|
except Exception as e:
|
|
|
|
except Exception as e:
|
|
|
|
raise AnsibleError("Failed to remove role %s: %s" % (role_name, str(e)))
|
|
|
|
raise AnsibleError("Failed to remove role %s: %s" % (role_name, str(e)))
|
|
|
|
|
|
|
|
|
|
|
@ -429,9 +434,9 @@ class GalaxyCLI(CLI):
|
|
|
|
if not version:
|
|
|
|
if not version:
|
|
|
|
version = "(unknown version)"
|
|
|
|
version = "(unknown version)"
|
|
|
|
# show some more info about single roles here
|
|
|
|
# show some more info about single roles here
|
|
|
|
self.display.display("- %s, %s" % (name, version))
|
|
|
|
display.display("- %s, %s" % (name, version))
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
self.display.display("- the role %s was not found" % name)
|
|
|
|
display.display("- the role %s was not found" % name)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
# show all valid roles in the roles_path directory
|
|
|
|
# show all valid roles in the roles_path directory
|
|
|
|
roles_path = self.get_opt('roles_path')
|
|
|
|
roles_path = self.get_opt('roles_path')
|
|
|
@ -450,7 +455,7 @@ class GalaxyCLI(CLI):
|
|
|
|
version = install_info.get("version", None)
|
|
|
|
version = install_info.get("version", None)
|
|
|
|
if not version:
|
|
|
|
if not version:
|
|
|
|
version = "(unknown version)"
|
|
|
|
version = "(unknown version)"
|
|
|
|
self.display.display("- %s, %s" % (path_file, version))
|
|
|
|
display.display("- %s, %s" % (path_file, version))
|
|
|
|
return 0
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
def execute_search(self):
|
|
|
|
def execute_search(self):
|
|
|
@ -464,7 +469,7 @@ class GalaxyCLI(CLI):
|
|
|
|
response = self.api.search_roles(search, self.options.platforms, self.options.tags)
|
|
|
|
response = self.api.search_roles(search, self.options.platforms, self.options.tags)
|
|
|
|
|
|
|
|
|
|
|
|
if 'count' in response:
|
|
|
|
if 'count' in response:
|
|
|
|
self.galaxy.display.display("Found %d roles matching your search:\n" % response['count'])
|
|
|
|
display.display("Found %d roles matching your search:\n" % response['count'])
|
|
|
|
|
|
|
|
|
|
|
|
data = ''
|
|
|
|
data = ''
|
|
|
|
if 'results' in response:
|
|
|
|
if 'results' in response:
|
|
|
|