From 19d390135e134feeeaf0305cc534f21ea25a9883 Mon Sep 17 00:00:00 2001 From: Will Thames Date: Thu, 14 Apr 2016 13:26:15 +1000 Subject: [PATCH] Improve galaxy handling of tgz roles Gerrithub presents tgz downloads that do not have a containing directory. This causes a stack trace. As all roles must contain a meta/main.yml, change ansible-galaxy to use that to determine the enclosing directory (in the case of multiple meta/main.yml files, use the one with the shortest parent) Fixes #15413 --- lib/ansible/galaxy/role.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/ansible/galaxy/role.py b/lib/ansible/galaxy/role.py index 1727931ad86..67bdc95b57e 100644 --- a/lib/ansible/galaxy/role.py +++ b/lib/ansible/galaxy/role.py @@ -272,8 +272,17 @@ class GalaxyRole(object): # next find the metadata file for member in members: if self.META_MAIN in member.name: - meta_file = member - break + # Look for parent of meta/main.yml + # Due to possibility of sub roles each containing meta/main.yml + # look for shortest length parent + meta_parent_dir = os.path.dirname(os.path.dirname(member.name)) + if not meta_file: + archive_parent_dir = meta_parent_dir + meta_file = member + else: + if len(meta_parent_dir) < len(archive_parent_dir): + archive_parent_dir = meta_parent_dir + meta_file = member if not meta_file: raise AnsibleError("this role does not appear to have a meta/main.yml file.") else: @@ -282,9 +291,9 @@ class GalaxyRole(object): except: raise AnsibleError("this role does not appear to have a valid meta/main.yml file.") - # we strip off the top-level directory for all of the files contained within - # the tar file here, since the default is 'github_repo-target', and change it - # to the specified role's name + # we strip off any higher-level directories for all of the files contained within + # the tar file here. The default is 'github_repo-target'. Gerrit instances, on the other + # hand, does not have a parent directory at all. installed = False while not installed: display.display("- extracting %s to %s" % (self.name, self.path)) @@ -305,9 +314,9 @@ class GalaxyRole(object): for member in members: # we only extract files, and remove any relative path # bits that might be in the file for security purposes - # and drop the leading directory, as mentioned above + # and drop any containing directory, as mentioned above if member.isreg() or member.issym(): - parts = member.name.split(os.sep)[1:] + parts = member.name.replace(archive_parent_dir, "").split(os.sep) final_parts = [] for part in parts: if part != '..' and '~' not in part and '$' not in part: