summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Thames <will@thames.id.au>2014-08-18 13:27:41 +0200
committerMichael DeHaan <michael@ansible.com>2014-08-21 23:15:23 +0200
commitada9074276ea9eecd082fe6db5f56b7fd2a6e2ef (patch)
tree92be76995c305a3879e2ab2dc854eecdc8908181
parentFriendly Role Names and roles from URLs (diff)
downloadansible-ada9074276ea9eecd082fe6db5f56b7fd2a6e2ef.tar.xz
ansible-ada9074276ea9eecd082fe6db5f56b7fd2a6e2ef.zip
Allow installation of roles from yaml roles file
Added docs Added more tests Improved how roles are returned from the parsers
-rwxr-xr-xbin/ansible-galaxy51
-rw-r--r--docsite/rst/playbooks_roles.rst7
-rw-r--r--lib/ansible/playbook/play.py5
-rw-r--r--lib/ansible/utils/__init__.py12
-rw-r--r--test/integration/Makefile15
-rw-r--r--test/integration/galaxy_playbook.yml1
-rw-r--r--test/integration/galaxy_roles.yml8
7 files changed, 71 insertions, 28 deletions
diff --git a/bin/ansible-galaxy b/bin/ansible-galaxy
index afc2d9de85..3c624693b3 100755
--- a/bin/ansible-galaxy
+++ b/bin/ansible-galaxy
@@ -696,10 +696,12 @@ def execute_install(args, options, parser):
roles_done = []
if role_file:
- # roles listed in a file, one per line
- # so we'll go through and grab them all
f = open(role_file, 'r')
- roles_left = f.readlines()
+ 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
+ roles_left = map(ansible.utils.role_spec_parse, f.readlines())
f.close()
else:
# roles were specified directly, so we'll just go out grab them
@@ -708,16 +710,18 @@ def execute_install(args, options, parser):
while len(roles_left) > 0:
# query the galaxy API for the role data
- (scm, role_src, role_version, role_name) = ansible.utils.role_spec_parse(roles_left.pop(0))
role_data = None
+ role = roles_left.pop(0)
+ role_src = role.get("src")
+ role_scm = role.get("scm")
if os.path.isfile(role_src):
# installing a local tar.gz
tmp_file = role_src
else:
- if scm:
+ if role_scm:
# create tar file from scm url
- tmp_file = scm_archive_role(scm, role_src, role_version, role_name)
+ tmp_file = scm_archive_role(role_scm, role_src, role.get("version"), role.get("name"))
elif '://' in role_src:
# just download a URL - version will probably be in the URL
tmp_file = fetch_role(role_src, None, None, options)
@@ -729,7 +733,7 @@ def execute_install(args, options, parser):
continue
role_versions = api_fetch_role_related(api_server, 'versions', role_data['id'])
- if not role_version:
+ if "version" not in role:
# 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
@@ -737,40 +741,43 @@ def execute_install(args, options, parser):
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])
+ role["version"] = str(loose_versions[-1])
else:
- role_version = 'master'
- print " no version specified, installing %s" % role_version
+ role["version"] = 'master'
+ print " no version specified, installing %s" % role.version
else:
- if role_versions and role_version not in [a.get('name',None) for a in role_versions]:
- print "The specified version (%s) was not found in the list of available versions." % role_version
+ if role_versions and role["version"] not in [a.get('name',None) for a in role_versions]:
+ print "The specified version (%s) was not found in the list of available versions." % role.version
exit_without_ignore(options)
continue
# download the role. if --no-deps was specified, we stop here,
# otherwise we recursively grab roles and all of their deps.
- tmp_file = fetch_role(role_src, role_version, role_data, options)
- if tmp_file and install_role(role_name, role_version, tmp_file, options):
+ tmp_file = fetch_role(role_src, role["version"], role_data, options)
+ if tmp_file and install_role(role.get("name"), role.get("version"), tmp_file, options):
# we're done with the temp file, clean it up
os.unlink(tmp_file)
# install dependencies, if we want them
if not no_deps:
if not role_data:
- role_data = get_role_metadata(role_name, options)
+ role_data = get_role_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_name in role_dependencies:
- #dep_name = "%s.%s" % (dep['owner'], dep['name'])
- if not get_role_metadata(dep_name.split('/')[-1], options):
- print ' adding dependency: %s' % dep_name
- roles_left.append(dep_name)
+ for dep in role_dependencies:
+ if isinstance(dep, str):
+ dep = ansible.utils.role_spec_parse(dep)
+ else:
+ dep = ansible.utils.role_yaml_parse(dep)
+ if not get_role_metadata(dep["name"], options):
+ print ' adding dependency: %s' % dep["name"]
+ roles_left.append(dep)
else:
- print ' dependency %s is already installed, skipping.' % dep_name
+ print ' dependency %s is already installed, skipping.' % dep["name"]
else:
if tmp_file:
os.unlink(tmp_file)
- print "%s was NOT installed successfully." % role_name
+ print "%s was NOT installed successfully." % role.get("name")
exit_without_ignore(options)
sys.exit(0)
diff --git a/docsite/rst/playbooks_roles.rst b/docsite/rst/playbooks_roles.rst
index 233ba9becf..4ce69a7130 100644
--- a/docsite/rst/playbooks_roles.rst
+++ b/docsite/rst/playbooks_roles.rst
@@ -299,6 +299,13 @@ Role dependencies can also be specified as a full path, just like top level role
dependencies:
- { role: '/path/to/common/roles/foo', x: 1 }
+Role dependencies can also be installed from source control repos or tar files, using a comma separated format of path, an optional version (tag, commit, branch etc) and optional friendly role name (an attempt is made to derive a role name from the repo name or archive filename)::
+
+ ---
+ dependencies:
+ - { role: 'git+http://git.example.com/repos/role-foo,v1.1,foo' }
+ - { role: '/path/to/tar/file.tgz,,friendly-name' }
+
Roles dependencies are always executed before the role that includes them, and are recursive. By default,
roles can also only be added as a dependency once - if another role also lists it as a dependency it will
not be run again. This behavior can be overridden by adding `allow_duplicates: yes` to the `meta/main.yml` file.
diff --git a/lib/ansible/playbook/play.py b/lib/ansible/playbook/play.py
index cdbab8c59e..50bd99173c 100644
--- a/lib/ansible/playbook/play.py
+++ b/lib/ansible/playbook/play.py
@@ -187,7 +187,7 @@ class Play(object):
raise errors.AnsibleError("expected a role name in dictionary: %s" % orig_path)
role_vars = orig_path
else:
- (scm, role_src, role_version, role_name) = utils.role_spec_parse(orig_path)
+ role_name = utils.role_spec_parse(orig_path)["name"]
role_path = None
@@ -412,8 +412,7 @@ class Play(object):
if isinstance(role, dict):
role_name = role['role']
else:
- role_name = role
- (scm, role_src, role_version, role_name) = utils.role_spec_parse(role_name)
+ role_name = utils.role_spec_parse(role)["name"]
role_names.append(role_name)
if os.path.isfile(task):
diff --git a/lib/ansible/utils/__init__.py b/lib/ansible/utils/__init__.py
index 65dc80150b..5692d6986b 100644
--- a/lib/ansible/utils/__init__.py
+++ b/lib/ansible/utils/__init__.py
@@ -380,7 +380,17 @@ def role_spec_parse(role_spec):
role_name = tokens[2]
else:
role_name = repo_url_to_role_name(tokens[0])
- return (scm, role_url, role_version, role_name)
+ return dict(scm=scm, src=role_url, version=role_version, name=role_name)
+
+
+def role_yaml_parse(role):
+ if '+' in role["src"]:
+ (scm, src) = role["src"].split('+')
+ role["scm"] = scm
+ role["src"] = src
+ if 'name' not in role:
+ role["name"] = repo_url_to_role_name(role["src"])
+ return role
def json_loads(data):
diff --git a/test/integration/Makefile b/test/integration/Makefile
index e31b820e8b..8188680c50 100644
--- a/test/integration/Makefile
+++ b/test/integration/Makefile
@@ -105,11 +105,22 @@ rackspace: $(CREDENTIALS_FILE)
CLOUD_RESOURCE_PREFIX="$(CLOUD_RESOURCE_PREFIX)" make rackspace_cleanup ; \
exit $$RC;
-test_galaxy:
+test_galaxy: test_galaxy_spec test_galaxy_yaml
+
+test_galaxy_spec:
mytmpdir=$(TMPDIR) ; \
ansible-galaxy install -r galaxy_rolesfile -p $$mytmpdir/roles ; \
cp galaxy_playbook.yml $$mytmpdir ; \
ansible-playbook -i $(INVENTORY) $$mytmpdir/galaxy_playbook.yml -v $(TEST_FLAGS) ; \
RC=$$? ; \
rm -rf $$mytmpdir ; \
- exit $$RC
+ exit $$RC
+
+test_galaxy_yaml:
+ mytmpdir=$(TMPDIR) ; \
+ ansible-galaxy install -r galaxy_roles.yml -p $$mytmpdir/roles ; \
+ cp galaxy_playbook.yml $$mytmpdir ; \
+ ansible-playbook -i $(INVENTORY) $$mytmpdir/galaxy_playbook.yml -v $(TEST_FLAGS) ; \
+ RC=$$? ; \
+ rm -rf $$mytmpdir ; \
+ exit $$RC
diff --git a/test/integration/galaxy_playbook.yml b/test/integration/galaxy_playbook.yml
index d7adebf340..8e64798c70 100644
--- a/test/integration/galaxy_playbook.yml
+++ b/test/integration/galaxy_playbook.yml
@@ -4,3 +4,4 @@
roles:
- "git-ansible-galaxy"
- "http-role"
+ - "hg-ansible-galaxy"
diff --git a/test/integration/galaxy_roles.yml b/test/integration/galaxy_roles.yml
new file mode 100644
index 0000000000..f354f5985f
--- /dev/null
+++ b/test/integration/galaxy_roles.yml
@@ -0,0 +1,8 @@
+- src: git+http://bitbucket.org/willthames/git-ansible-galaxy
+ version: v1.4
+
+- src: ssh://hg@bitbucket.org/willthames/hg-ansible-galaxy
+ scm: hg
+
+- src: https://bitbucket.org/willthames/http-ansible-galaxy/get/master.tar.gz
+ name: http-role