From d60bc492b6e405ebcde929b4b9e8b8bdf59f1be4 Mon Sep 17 00:00:00 2001 From: Chris Houseknecht Date: Thu, 27 Oct 2016 22:16:22 -0400 Subject: [PATCH] Add --container-enabled option to `ansible-galaxy init` command. (#18157) --- lib/ansible/cli/galaxy.py | 124 ++++++++---------- lib/ansible/galaxy/__init__.py | 39 +----- .../galaxy/data/container_enabled/.travis.yml | 46 +++++++ .../galaxy/data/container_enabled/README.md | 49 +++++++ .../container_enabled/defaults/main.yml.j2 | 3 + .../container_enabled/handlers/main.yml.j2 | 2 + .../container_enabled/meta/container.yml.j2 | 11 ++ .../data/container_enabled/meta/main.yml.j2 | 56 ++++++++ .../data/container_enabled/tasks/main.yml.j2 | 3 + .../data/container_enabled/tests/ansible.cfg | 2 + .../data/container_enabled/tests/inventory | 3 + .../data/container_enabled/tests/test.yml.j2 | 8 ++ .../data/container_enabled/vars/main.yml.j2 | 3 + .../data/{travis.j2 => default/.travis.yml} | 0 .../galaxy/data/{readme => default/README.md} | 0 .../galaxy/data/default/defaults/main.yml.j2 | 2 + .../galaxy/data/default/handlers/main.yml.j2 | 2 + .../meta/main.yml.j2} | 0 .../galaxy/data/default/tasks/main.yml.j2 | 2 + .../galaxy/data/default/tests/inventory | 2 + .../tests/test.yml.j2} | 0 .../galaxy/data/default/vars/main.yml.j2 | 2 + lib/ansible/modules/core | 2 +- 23 files changed, 254 insertions(+), 107 deletions(-) create mode 100644 lib/ansible/galaxy/data/container_enabled/.travis.yml create mode 100644 lib/ansible/galaxy/data/container_enabled/README.md create mode 100644 lib/ansible/galaxy/data/container_enabled/defaults/main.yml.j2 create mode 100644 lib/ansible/galaxy/data/container_enabled/handlers/main.yml.j2 create mode 100644 lib/ansible/galaxy/data/container_enabled/meta/container.yml.j2 create mode 100644 lib/ansible/galaxy/data/container_enabled/meta/main.yml.j2 create mode 100644 lib/ansible/galaxy/data/container_enabled/tasks/main.yml.j2 create mode 100644 lib/ansible/galaxy/data/container_enabled/tests/ansible.cfg create mode 100644 lib/ansible/galaxy/data/container_enabled/tests/inventory create mode 100644 lib/ansible/galaxy/data/container_enabled/tests/test.yml.j2 create mode 100644 lib/ansible/galaxy/data/container_enabled/vars/main.yml.j2 rename lib/ansible/galaxy/data/{travis.j2 => default/.travis.yml} (100%) rename lib/ansible/galaxy/data/{readme => default/README.md} (100%) create mode 100644 lib/ansible/galaxy/data/default/defaults/main.yml.j2 create mode 100644 lib/ansible/galaxy/data/default/handlers/main.yml.j2 rename lib/ansible/galaxy/data/{metadata_template.j2 => default/meta/main.yml.j2} (100%) create mode 100644 lib/ansible/galaxy/data/default/tasks/main.yml.j2 create mode 100644 lib/ansible/galaxy/data/default/tests/inventory rename lib/ansible/galaxy/data/{test_playbook.j2 => default/tests/test.yml.j2} (100%) create mode 100644 lib/ansible/galaxy/data/default/vars/main.yml.j2 diff --git a/lib/ansible/cli/galaxy.py b/lib/ansible/cli/galaxy.py index ca5fe7fb268..00efa1e81cc 100644 --- a/lib/ansible/cli/galaxy.py +++ b/lib/ansible/cli/galaxy.py @@ -26,9 +26,10 @@ import os.path import sys import yaml import time +import shutil from collections import defaultdict -from jinja2 import Environment +from jinja2 import Environment, FileSystemLoader import ansible.constants as C from ansible.cli import CLI @@ -85,6 +86,8 @@ class GalaxyCLI(CLI): elif self.action == "init": self.parser.set_usage("usage: %prog init [options] role_name") self.parser.add_option('-p', '--init-path', dest='init_path', default="./", help='The path in which the skeleton role will be created. The default is the current working directory.') + self.parser.add_option('--container-enabled', dest='container_enabled', action='store_true', default=False, + help='Initialize the skeleton role with default contents for a Container Enabled role.') elif self.action == "install": self.parser.set_usage("usage: %prog install [options] [-r FILE | role_name(s)[,version] | scm+role_repo_url[,version] | tar_file(s)]") self.parser.add_option('-i', '--ignore-errors', dest='ignore_errors', action='store_true', default=False, help='Ignore errors and continue with the next specified role.') @@ -188,79 +191,58 @@ class GalaxyCLI(CLI): "however it will reset any main.yml files that may have\n" "been modified there already." % role_path) - # create default README.md + platforms = [] + if not offline: + platforms = self.api.get_list("platforms") or [] + + # group the list of platforms from the api based + # on their names, with the release field being + # appended to a list of versions + platform_groups = defaultdict(list) + for platform in platforms: + platform_groups[platform['name']].append(platform['release']) + platform_groups[platform['name']].sort() + + inject_data = dict( + role_name=role_name, + author='your name', + description='your description', + company='your company (optional)', + license='license (GPLv2, CC-BY, etc)', + issue_tracker_url='http://example.com/issue/tracker', + min_ansible_version='1.2', + platforms=platform_groups, + container_enabled=self.options.container_enabled + ) + + # create role directory if not os.path.exists(role_path): os.makedirs(role_path) - readme_path = os.path.join(role_path, "README.md") - f = open(readme_path, "wb") - f.write(to_bytes(self.galaxy.default_readme)) - f.close() - - # create default .travis.yml - travis = Environment().from_string(self.galaxy.default_travis).render() - f = open(os.path.join(role_path, '.travis.yml'), 'w') - f.write(travis) - f.close() - - for dir in GalaxyRole.ROLE_DIRS: - dir_path = os.path.join(init_path, role_name, dir) - main_yml_path = os.path.join(dir_path, 'main.yml') - - # create the directory if it doesn't exist already - if not os.path.exists(dir_path): - os.makedirs(dir_path) - - # now create the main.yml file for that directory - if dir == "meta": - # create a skeleton meta/main.yml with a valid galaxy_info - # datastructure in place, plus with all of the available - # platforms included (but commented out), the galaxy_tags - # list, and the dependencies section - platforms = [] - if not offline: - platforms = self.api.get_list("platforms") or [] - - # group the list of platforms from the api based - # on their names, with the release field being - # appended to a list of versions - platform_groups = defaultdict(list) - for platform in platforms: - platform_groups[platform['name']].append(platform['release']) - platform_groups[platform['name']].sort() - - inject = dict( - author = 'your name', - description = 'your description', - company = 'your company (optional)', - license = 'license (GPLv2, CC-BY, etc)', - issue_tracker_url = 'http://example.com/issue/tracker', - min_ansible_version = '1.2', - platforms = platform_groups, - ) - rendered_meta = Environment().from_string(self.galaxy.default_meta).render(inject) - f = open(main_yml_path, 'w') - f.write(rendered_meta) - f.close() - pass - elif dir == "tests": - # create tests/test.yml - inject = dict( - role_name = role_name - ) - playbook = Environment().from_string(self.galaxy.default_test).render(inject) - f = open(os.path.join(dir_path, 'test.yml'), 'w') - f.write(playbook) - f.close() - # create tests/inventory - f = open(os.path.join(dir_path, 'inventory'), 'w') - f.write('localhost') - f.close() - elif dir not in ('files','templates'): - # just write a (mostly) empty YAML file for main.yml - f = open(main_yml_path, 'w') - f.write('---\n# %s file for %s\n' % (dir,role_name)) - f.close() + role_skeleton = self.galaxy.default_role_skeleton_path + role_skeleton = os.path.expanduser(role_skeleton) + template_env = Environment(loader=FileSystemLoader(role_skeleton)) + + for root, dirs, files in os.walk(role_skeleton, topdown=True): + rel_root = os.path.relpath(root, role_skeleton) + in_templates_dir = rel_root.split(os.sep, 1)[0] == 'templates' + for f in files: + filename, ext = os.path.splitext(f) + if ext == ".j2" and not in_templates_dir: + src_template = os.path.join(rel_root, f) + dest_file = os.path.join(role_path, rel_root, filename) + template_env.get_template(src_template).stream(inject_data).dump(dest_file) + else: + display.display("root: %s f: %s role_skeleton: %s" % (root, f, role_skeleton)) + f_rel_path = os.path.relpath(os.path.join(root, f), role_skeleton) + display.display("f_rel_path: %s" % f_rel_path) + shutil.copyfile(os.path.join(root, f), os.path.join(role_path, f_rel_path)) + + for d in dirs: + dir_path = os.path.join(role_path, rel_root, d) + if not os.path.exists(dir_path): + os.makedirs(dir_path) + display.display("- %s was created successfully" % role_name) def execute_info(self): diff --git a/lib/ansible/galaxy/__init__.py b/lib/ansible/galaxy/__init__.py index 8fdd24e9109..129e860c907 100644 --- a/lib/ansible/galaxy/__init__.py +++ b/lib/ansible/galaxy/__init__.py @@ -48,46 +48,15 @@ class Galaxy(object): # load data path for resource usage this_dir, this_filename = os.path.split(__file__) - self.DATA_PATH = os.path.join(this_dir, "data") - - self._default_readme = None - self._default_meta = None - self._default_test = None - self._default_travis = None - - @property - def default_readme(self): - if self._default_readme is None: - self._default_readme = self._str_from_data_file('readme') - return self._default_readme - - @property - def default_meta(self): - if self._default_meta is None: - self._default_meta = self._str_from_data_file('metadata_template.j2') - return self._default_meta - - @property - def default_test(self): - if self._default_test is None: - self._default_test = self._str_from_data_file('test_playbook.j2') - return self._default_test + type_path = 'container_enabled' if getattr(self.options, 'container_enabled', False) else 'default' + self.DATA_PATH = os.path.join(this_dir, 'data', type_path) @property - def default_travis(self): - if self._default_travis is None: - self._default_travis = self._str_from_data_file('travis.j2') - return self._default_travis + def default_role_skeleton_path(self): + return self.DATA_PATH def add_role(self, role): self.roles[role.name] = role def remove_role(self, role_name): del self.roles[role_name] - - def _str_from_data_file(self, filename): - myfile = os.path.join(self.DATA_PATH, filename) - try: - return open(myfile).read() - except Exception as e: - raise AnsibleError("Could not open %s: %s" % (filename, str(e))) diff --git a/lib/ansible/galaxy/data/container_enabled/.travis.yml b/lib/ansible/galaxy/data/container_enabled/.travis.yml new file mode 100644 index 00000000000..53f71f4f769 --- /dev/null +++ b/lib/ansible/galaxy/data/container_enabled/.travis.yml @@ -0,0 +1,46 @@ +language: python +dist: trusty +sudo: required + +services: + - docker + +before_install: + - sudo apt-add-repository 'deb http://archive.ubuntu.com/ubuntu trusty-backports universe' + - sudo apt-get update -qq + - sudo apt-get install -y -o Dpkg::Options::="--force-confold" --force-yes docker-engine + +install: + # Install the latest Ansible Container and Ansible + - pip install git+https://github.com/ansible/ansible-container.git + - pip install ansible + +script: + # Make sure docker is functioning + - docker version + - docker-compose version + - docker info + + # Create an Ansible Container project + - mkdir -p tests + - cd tests + - ansible-container init + + # Install the role into the project + - echo "Installing and testing git+https://github.com/${TRAVIS_REPO_SLUG},${TRAVIS_COMMIT}" + - ansible-container install git+https://github.com/${TRAVIS_REPO_SLUG},${TRAVIS_COMMIT} + + # Build the service image + - ansible-container build + + # Start the service + - ansible-container run -d + - docker ps + + # Run tests + - ansible-playbook test.yml + +notifications: + email: false + webhooks: https://galaxy.ansible.com/api/v1/notifications/ + diff --git a/lib/ansible/galaxy/data/container_enabled/README.md b/lib/ansible/galaxy/data/container_enabled/README.md new file mode 100644 index 00000000000..2de963afe93 --- /dev/null +++ b/lib/ansible/galaxy/data/container_enabled/README.md @@ -0,0 +1,49 @@ +# Role Name + +Adds a service to your [Ansible Container](https://github.com/ansible/ansible-container) project. Run the following commands +to install the service: + +``` +# Set the working directory to your Ansible Container project root +$ cd myproject + +# Install the service +$ ansible-container install +``` + +## Requirements + +- [Ansible Container](https://github.com/ansible/ansible-container) +- An existing Ansible Container project. To create a project, simply run the following: + ``` + # Create an empty project directory + $ mkdir myproject + + # Set the working directory to the new directory + $ cd myproject + + # Initialize the project + $ ansible-contiainer init + ``` + +- Continue listing any prerequisites here... + + +## Role Variables + +A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set +via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. + +## Dependencies + +A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. + +## License + +BSD + +## Author Information + +An optional section for the role authors to include contact information, or a website (HTML is not allowed). + + diff --git a/lib/ansible/galaxy/data/container_enabled/defaults/main.yml.j2 b/lib/ansible/galaxy/data/container_enabled/defaults/main.yml.j2 new file mode 100644 index 00000000000..3da8d52cc1d --- /dev/null +++ b/lib/ansible/galaxy/data/container_enabled/defaults/main.yml.j2 @@ -0,0 +1,3 @@ +--- +# defaults file for {{ role_name }} + diff --git a/lib/ansible/galaxy/data/container_enabled/handlers/main.yml.j2 b/lib/ansible/galaxy/data/container_enabled/handlers/main.yml.j2 new file mode 100644 index 00000000000..3f4c49674d4 --- /dev/null +++ b/lib/ansible/galaxy/data/container_enabled/handlers/main.yml.j2 @@ -0,0 +1,2 @@ +--- +# handlers file for {{ role_name }} diff --git a/lib/ansible/galaxy/data/container_enabled/meta/container.yml.j2 b/lib/ansible/galaxy/data/container_enabled/meta/container.yml.j2 new file mode 100644 index 00000000000..f033d34110e --- /dev/null +++ b/lib/ansible/galaxy/data/container_enabled/meta/container.yml.j2 @@ -0,0 +1,11 @@ +# Add your Ansible Container service definitions here. +# For example: + # + # web: + # image: ubuntu:trusty + # ports: + # - "80:80" + # command: ['/usr/bin/dumb-init', '/usr/sbin/apache2ctl', '-D', 'FOREGROUND'] + # dev_overrides: + # environment: + # - "DEBUG=1" diff --git a/lib/ansible/galaxy/data/container_enabled/meta/main.yml.j2 b/lib/ansible/galaxy/data/container_enabled/meta/main.yml.j2 new file mode 100644 index 00000000000..7da00bc0d56 --- /dev/null +++ b/lib/ansible/galaxy/data/container_enabled/meta/main.yml.j2 @@ -0,0 +1,56 @@ +galaxy_info: + author: {{ author }} + description: {{ description }} + company: {{ company }} + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: {{ issue_tracker_url }} + + # Some suggested licenses: + # - BSD (default) + # - MIT + # - GPLv2 + # - GPLv3 + # - Apache + # - CC-BY + license: {{ license }} + + min_ansible_container_version: 0.2.0 + + # If Ansible is required outside of the build container, provide the minimum version: + # min_ansible_version: + + # Optionally specify the branch Galaxy will use when accessing the GitHub + # repo for this role. During role install, if no tags are available, + # Galaxy will use this branch. During import Galaxy will access files on + # this branch. If Travis integration is configured, only notifications for this + # branch will be accepted. Otherwise, in all cases, the repo's default branch + # (usually master) will be used. + #github_branch: + + # + # Below are all platforms currently available in Galaxy. Uncomment any that match the base images + # of the services defined in meta/container.yml + # + #platforms: + {%- for platform,versions in platforms.items() %} + #- name: {{ platform }} + # versions: + # - all + {%- for version in versions %} + # - {{ version }} + {%- endfor -%} + {%- endfor %} + + galaxy_tags: + - container + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. diff --git a/lib/ansible/galaxy/data/container_enabled/tasks/main.yml.j2 b/lib/ansible/galaxy/data/container_enabled/tasks/main.yml.j2 new file mode 100644 index 00000000000..115d841bdae --- /dev/null +++ b/lib/ansible/galaxy/data/container_enabled/tasks/main.yml.j2 @@ -0,0 +1,3 @@ +--- +# tasks file for {{ role_name }} + diff --git a/lib/ansible/galaxy/data/container_enabled/tests/ansible.cfg b/lib/ansible/galaxy/data/container_enabled/tests/ansible.cfg new file mode 100644 index 00000000000..2f74f1b2722 --- /dev/null +++ b/lib/ansible/galaxy/data/container_enabled/tests/ansible.cfg @@ -0,0 +1,2 @@ +[defaults] +inventory=./inventory diff --git a/lib/ansible/galaxy/data/container_enabled/tests/inventory b/lib/ansible/galaxy/data/container_enabled/tests/inventory new file mode 100644 index 00000000000..ea69cbf1225 --- /dev/null +++ b/lib/ansible/galaxy/data/container_enabled/tests/inventory @@ -0,0 +1,3 @@ +localhost + + diff --git a/lib/ansible/galaxy/data/container_enabled/tests/test.yml.j2 b/lib/ansible/galaxy/data/container_enabled/tests/test.yml.j2 new file mode 100644 index 00000000000..224ea3113e2 --- /dev/null +++ b/lib/ansible/galaxy/data/container_enabled/tests/test.yml.j2 @@ -0,0 +1,8 @@ +--- +- hosts: localhost + gather_facts: no + connection: local + tasks: + + # Add tasks and assertions for testing the service here. + diff --git a/lib/ansible/galaxy/data/container_enabled/vars/main.yml.j2 b/lib/ansible/galaxy/data/container_enabled/vars/main.yml.j2 new file mode 100644 index 00000000000..b0524ec32aa --- /dev/null +++ b/lib/ansible/galaxy/data/container_enabled/vars/main.yml.j2 @@ -0,0 +1,3 @@ +--- +# vars file for {{ role_name }} + diff --git a/lib/ansible/galaxy/data/travis.j2 b/lib/ansible/galaxy/data/default/.travis.yml similarity index 100% rename from lib/ansible/galaxy/data/travis.j2 rename to lib/ansible/galaxy/data/default/.travis.yml diff --git a/lib/ansible/galaxy/data/readme b/lib/ansible/galaxy/data/default/README.md similarity index 100% rename from lib/ansible/galaxy/data/readme rename to lib/ansible/galaxy/data/default/README.md diff --git a/lib/ansible/galaxy/data/default/defaults/main.yml.j2 b/lib/ansible/galaxy/data/default/defaults/main.yml.j2 new file mode 100644 index 00000000000..3818e64c335 --- /dev/null +++ b/lib/ansible/galaxy/data/default/defaults/main.yml.j2 @@ -0,0 +1,2 @@ +--- +# defaults file for {{ role_name }} diff --git a/lib/ansible/galaxy/data/default/handlers/main.yml.j2 b/lib/ansible/galaxy/data/default/handlers/main.yml.j2 new file mode 100644 index 00000000000..3f4c49674d4 --- /dev/null +++ b/lib/ansible/galaxy/data/default/handlers/main.yml.j2 @@ -0,0 +1,2 @@ +--- +# handlers file for {{ role_name }} diff --git a/lib/ansible/galaxy/data/metadata_template.j2 b/lib/ansible/galaxy/data/default/meta/main.yml.j2 similarity index 100% rename from lib/ansible/galaxy/data/metadata_template.j2 rename to lib/ansible/galaxy/data/default/meta/main.yml.j2 diff --git a/lib/ansible/galaxy/data/default/tasks/main.yml.j2 b/lib/ansible/galaxy/data/default/tasks/main.yml.j2 new file mode 100644 index 00000000000..a9880650590 --- /dev/null +++ b/lib/ansible/galaxy/data/default/tasks/main.yml.j2 @@ -0,0 +1,2 @@ +--- +# tasks file for {{ role_name }} diff --git a/lib/ansible/galaxy/data/default/tests/inventory b/lib/ansible/galaxy/data/default/tests/inventory new file mode 100644 index 00000000000..878877b0776 --- /dev/null +++ b/lib/ansible/galaxy/data/default/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/lib/ansible/galaxy/data/test_playbook.j2 b/lib/ansible/galaxy/data/default/tests/test.yml.j2 similarity index 100% rename from lib/ansible/galaxy/data/test_playbook.j2 rename to lib/ansible/galaxy/data/default/tests/test.yml.j2 diff --git a/lib/ansible/galaxy/data/default/vars/main.yml.j2 b/lib/ansible/galaxy/data/default/vars/main.yml.j2 new file mode 100644 index 00000000000..092d511a1e6 --- /dev/null +++ b/lib/ansible/galaxy/data/default/vars/main.yml.j2 @@ -0,0 +1,2 @@ +--- +# vars file for {{ role_name }} diff --git a/lib/ansible/modules/core b/lib/ansible/modules/core index c51ced56cce..124bb924169 160000 --- a/lib/ansible/modules/core +++ b/lib/ansible/modules/core @@ -1 +1 @@ -Subproject commit c51ced56cce443e481c4edc7f95fd3f3c95f8c20 +Subproject commit 124bb9241694aa5492a85e7abfabd3720ae2b682