From a8b8ff5c5996b025452d36fd464985e98c9da0bb Mon Sep 17 00:00:00 2001 From: David Moreau Simard Date: Fri, 29 Nov 2019 12:24:46 -0500 Subject: [PATCH] callback: Add support for specifying default playbook labels This allows users to set default playbooks labels without needing to specify the 'ara_playbook_label' variable. In practice, it can be used to set labels on playbooks without needing to modify playbooks or the playbook vars. Fixes: https://github.com/ansible-community/ara/issues/95 Change-Id: Ib1d3b33d1766905061e5534677764aa9c42a99b0 --- ara/plugins/callback/ara_default.py | 26 ++++++++++- doc/source/ara-plugin-configuration.rst | 2 + doc/source/playbook-names-and-labels.rst | 56 ++++++++++++++---------- tests/basic.yaml | 11 +++++ tests/test_tasks.yaml | 11 +++++ 5 files changed, 81 insertions(+), 25 deletions(-) diff --git a/ara/plugins/callback/ara_default.py b/ara/plugins/callback/ara_default.py index d4ee04c9..ae051df6 100644 --- a/ara/plugins/callback/ara_default.py +++ b/ara/plugins/callback/ara_default.py @@ -105,6 +105,15 @@ options: ini: - section: ara key: api_timeout + default_labels: + description: A list of default labels that will be applied to playbooks + type: list + default: [] + env: + - name: ARA_DEFAULT_LABELS + ini: + - section: ara + key: default_labels ignored_facts: description: List of host facts that will not be saved by ARA type: list @@ -154,6 +163,7 @@ class CallbackModule(CallbackBase): def set_options(self, task_keys=None, var_options=None, direct=None): super(CallbackModule, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct) + self.default_labels = self.get_option("default_labels") self.ignored_facts = self.get_option("ignored_facts") self.ignored_arguments = self.get_option("ignored_arguments") @@ -206,8 +216,20 @@ class CallbackModule(CallbackBase): play_vars = play._variable_manager.get_vars(play=play)["vars"] if "ara_playbook_name" in play_vars: self._set_playbook_name(name=play_vars["ara_playbook_name"]) + + labels = self.default_labels if "ara_playbook_labels" in play_vars: - self._set_playbook_labels(labels=play_vars["ara_playbook_labels"]) + # ara_playbook_labels can be supplied as a list inside a playbook + # but it might also be specified as a comma separated string when + # using extra-vars + if isinstance(play_vars["ara_playbook_labels"], list): + labels.extend(play_vars["ara_playbook_labels"]) + elif isinstance(play_vars["ara_playbook_labels"], str): + labels.extend(play_vars["ara_playbook_labels"].split(",")) + else: + raise TypeError("ara_playbook_labels must be a list or a comma-separated string") + if labels: + self._set_playbook_labels(labels=labels) # Record all the files involved in the play for path in play._loader._FILE_CACHE.keys(): @@ -307,7 +329,7 @@ class CallbackModule(CallbackBase): self.playbook = self.client.patch("/api/v1/playbooks/%s" % self.playbook["id"], name=name) def _set_playbook_labels(self, labels): - if self.playbook["labels"] != labels: + if sorted(self.playbook["labels"]) != sorted(labels): self.playbook = self.client.patch("/api/v1/playbooks/%s" % self.playbook["id"], labels=labels) def _get_or_create_file(self, path): diff --git a/doc/source/ara-plugin-configuration.rst b/doc/source/ara-plugin-configuration.rst index 497543dd..955a76a7 100644 --- a/doc/source/ara-plugin-configuration.rst +++ b/doc/source/ara-plugin-configuration.rst @@ -48,6 +48,7 @@ an ``ansible.cfg`` file: api_username = user api_password = password api_timeout = 15 + default_labels = dev,deploy ignored_facts = '["ansible_env", "ansible_all_ipv4_addresses"]' ignored_arguments = '["extra_vars", "vault_password_files"]' @@ -60,6 +61,7 @@ or as environment variables: export ARA_API_USERNAME=user export ARA_API_PASSWORD=password export ARA_API_TIMEOUT=15 + export ARA_DEFAULT_LABELS=dev,deploy export ARA_IGNORED_FACTS='["ansible_env", "ansible_all_ipv4_addresses"]' export ARA_IGNORED_ARGUMENTS='["extra_vars", "vault_password_files"]' diff --git a/doc/source/playbook-names-and-labels.rst b/doc/source/playbook-names-and-labels.rst index c5091eef..f05adc24 100644 --- a/doc/source/playbook-names-and-labels.rst +++ b/doc/source/playbook-names-and-labels.rst @@ -1,33 +1,22 @@ -Setting playbook names and labels -================================= +Playbook names and labels +========================= -ARA provides the ability for users to specify playbook names and labels in -order to better distinguish playbooks run in different environments or purposes. +ARA allows users to specify playbook names and labels in order to better +distinguish playbooks run in different environments or for different purposes. -Names and labels are also searchable by the ARA API, allowing you to find -playbooks matching your query. +Once your playbooks have names and labels, the API allows you to easily search +for them, for example: + +- ``/api/v1/playbooks?name=`` +- ``/api/v1/playbooks?label=`` Names and labels are set as regular Ansible variables: - ``ara_playbook_name`` - ``ara_playbook_labels`` -These variables can be provided by your Ansible inventory, directly in your -playbook file, as extra-vars or any other way supported by Ansible. - -For example, in an inventory: - -.. code-block:: ini - - [dev] - host1 - host2 - - [dev:vars] - ara_playbook_name=deploy-dev - ara_playbook_labels='["deploy", "dev"]' - -In a playbook: +These variables are picked up by ARA at the beginning of a play and can be +provided directly in your playbook file: .. code-block:: yaml @@ -47,4 +36,25 @@ Or as extra-vars: ansible-playbook -i hosts playbook.yaml \ -e ara_playbook_name=deploy-dev \ - -e ara_playbook_labels='["deploy", "dev"]' + -e ara_playbook_labels=deploy,dev + +Default labels +-------------- + +If necessary, ARA can be configured to set one or more labels on every recorded +playbook by default. + +This can be done either through an ``ansible.cfg`` file like so: + +.. code-block:: ini + + [defaults] + # ... + [ara] + default_labels = first_label,second_label + +or through the ``ARA_DEFAULT_LABELS`` environment variable: + +.. code-block:: bash + + export ARA_DEFAULT_LABELS=first_label,second_label diff --git a/tests/basic.yaml b/tests/basic.yaml index 20a97dd6..e0744dda 100644 --- a/tests/basic.yaml +++ b/tests/basic.yaml @@ -89,6 +89,16 @@ command: "{{ ara_api_venv_path }}/bin/python -m ara.setup.plugins" register: ara_setup_plugins + - name: Set default labels with Zuul + set_fact: + _default_labels: + - "nodepool.provider:{{ nodepool.provider }}" + - "zuul.change:{{ zuul.change }}" + - "zuul.executor:{{ zuul.executor.hostname }}" + - "zuul.pipeline:{{ zuul.pipeline }}" + - "zuul.project:{{ zuul.project.canonical_name }}" + when: zuul is defined + # These aren't in the same task (i.e, with loop) so we can tell individual test # runs apart easily rather than keeping all the output bundled in a single task. # TODO: Add validation for the tests @@ -101,6 +111,7 @@ ARA_SECRET_KEY: "{{ ara_api_secret_key }}" ARA_API_CLIENT: "{{ ara_api_client | default('offline') }}" ARA_API_SERVER: "{{ ara_api_server | default('http://127.0.0.1:8000') }}" + ARA_DEFAULT_LABELS: "{{ _default_labels | join(', ') | default('default-label') }}" PATH: "{{ ara_api_venv_path }}/bin:/bin:/usr/bin:/usr/local/bin" vars: _test_root: "{{ ara_api_source }}/tests/integration" diff --git a/tests/test_tasks.yaml b/tests/test_tasks.yaml index 5dbc845b..956818a1 100644 --- a/tests/test_tasks.yaml +++ b/tests/test_tasks.yaml @@ -63,6 +63,16 @@ changed_when: false register: ara_setup_plugins +- name: Set default labels with Zuul + set_fact: + _default_labels: + - "nodepool.provider:{{ nodepool.provider }}" + - "zuul.change:{{ zuul.change }}" + - "zuul.executor:{{ zuul.executor.hostname }}" + - "zuul.pipeline:{{ zuul.pipeline }}" + - "zuul.project:{{ zuul.project.canonical_name }}" + when: zuul is defined + # These aren't in the same task (i.e, with loop) so we can tell individual test # runs apart easily rather than keeping all the output bundled in a single task. - environment: @@ -71,6 +81,7 @@ ARA_SETTINGS: "{{ ara_api_settings }}" ARA_API_CLIENT: "{{ ara_api_client | default('offline') }}" ARA_API_SERVER: "{{ ara_api_server | default('http://127.0.0.1:8000') }}" + ARA_DEFAULT_LABELS: "{{ _default_labels | join(', ') | default('default-label') }}" PATH: "{{ path_with_virtualenv | default('/usr/bin:/usr/local/bin') }}" vars: _test_root: "{{ ara_api_source_checkout }}/tests/integration"