From b8230cf465e70536ac47db84d211aede3fec1b4c Mon Sep 17 00:00:00 2001 From: David Danielsson Date: Fri, 27 Sep 2024 14:16:28 -0500 Subject: [PATCH 1/7] modified: credential/README.md modified: credential/meta/argument_specs.yml modified: credential/tasks/main.yml modified: credential/tests/test.yml modified: decision_environment/README.md modified: decision_environment/meta/argument_specs.yml modified: decision_environment/tasks/main.yml modified: decision_environment/tests/test.yml modified: dispatch/meta/argument_specs.yml modified: dispatch/tests/test.yml modified: project/README.md modified: project/meta/argument_specs.yml modified: project/tasks/main.yml modified: project/tests/test.yml deleted: project_sync/README.md deleted: project_sync/defaults/main.yml deleted: project_sync/meta/argument_specs.yml deleted: project_sync/meta/main.yml deleted: project_sync/tasks/main.yml deleted: project_sync/tests/test.yml deleted: project_sync/tests/vars/projects.yml modified: rulebook_activation/README.md modified: rulebook_activation/meta/argument_specs.yml modified: rulebook_activation/tasks/main.yml modified: rulebook_activation/tests/test.yml modified: user/README.md modified: user/meta/argument_specs.yml modified: user/tasks/main.yml modified: user/tests/test.yml modified: user_token/README.md modified: user_token/meta/argument_specs.yml modified: user_token/tasks/main.yml modified: user_token/tests/test.yml modified: ../README.md modified: ../galaxy.yml deleted: ../plugins/doc_fragments/auth.py deleted: ../plugins/doc_fragments/auth_plugin.py deleted: ../plugins/lookup/eda_api.py deleted: ../plugins/module_utils/eda_module.py deleted: ../plugins/modules/__init__.py deleted: ../plugins/modules/credential.py deleted: ../plugins/modules/decision_environment.py deleted: ../plugins/modules/project.py deleted: ../plugins/modules/project_sync.py deleted: ../plugins/modules/rulebook_activation.py deleted: ../plugins/modules/user.py deleted: ../plugins/modules/user_token.py modified: ../tests/playbooks/eda_configs/eda_auth.yml modified: ../tests/playbooks/testing_collections_playbook.yml --- README.md | 14 +- galaxy.yml | 3 +- plugins/doc_fragments/auth.py | 54 -- plugins/doc_fragments/auth_plugin.py | 43 - plugins/lookup/eda_api.py | 160 ---- plugins/module_utils/eda_module.py | 904 ------------------ plugins/modules/__init__.py | 0 plugins/modules/credential.py | 143 --- plugins/modules/decision_environment.py | 133 --- plugins/modules/project.py | 141 --- plugins/modules/project_sync.py | 95 -- plugins/modules/rulebook_activation.py | 233 ----- plugins/modules/user.py | 157 --- plugins/modules/user_token.py | 111 --- roles/credential/README.md | 8 +- roles/credential/meta/argument_specs.yml | 6 +- roles/credential/tasks/main.yml | 26 +- roles/credential/tests/test.yml | 2 +- roles/decision_environment/README.md | 5 +- .../meta/argument_specs.yml | 6 +- roles/decision_environment/tasks/main.yml | 25 +- roles/decision_environment/tests/test.yml | 2 +- roles/dispatch/meta/argument_specs.yml | 4 +- roles/dispatch/tests/test.yml | 4 +- roles/project/README.md | 6 +- roles/project/meta/argument_specs.yml | 6 +- roles/project/tasks/main.yml | 27 +- roles/project/tests/test.yml | 2 +- roles/project_sync/README.md | 105 -- roles/project_sync/defaults/main.yml | 8 - roles/project_sync/meta/argument_specs.yml | 70 -- roles/project_sync/meta/main.yml | 43 - roles/project_sync/tasks/main.yml | 41 - roles/project_sync/tests/test.yml | 20 - roles/project_sync/tests/vars/projects.yml | 11 - roles/rulebook_activation/README.md | 8 +- .../meta/argument_specs.yml | 6 +- roles/rulebook_activation/tasks/main.yml | 14 +- roles/rulebook_activation/tests/test.yml | 2 +- roles/user/README.md | 5 +- roles/user/meta/argument_specs.yml | 6 +- roles/user/tasks/main.yml | 31 +- roles/user/tests/test.yml | 2 +- roles/user_token/README.md | 4 +- roles/user_token/meta/argument_specs.yml | 6 +- roles/user_token/tasks/main.yml | 8 +- roles/user_token/tests/test.yml | 2 +- tests/playbooks/eda_configs/eda_auth.yml | 4 +- .../testing_collections_playbook.yml | 2 +- 49 files changed, 126 insertions(+), 2592 deletions(-) delete mode 100644 plugins/doc_fragments/auth.py delete mode 100644 plugins/doc_fragments/auth_plugin.py delete mode 100644 plugins/lookup/eda_api.py delete mode 100644 plugins/module_utils/eda_module.py delete mode 100644 plugins/modules/__init__.py delete mode 100644 plugins/modules/credential.py delete mode 100644 plugins/modules/decision_environment.py delete mode 100644 plugins/modules/project.py delete mode 100644 plugins/modules/project_sync.py delete mode 100644 plugins/modules/rulebook_activation.py delete mode 100644 plugins/modules/user.py delete mode 100644 plugins/modules/user_token.py delete mode 100644 roles/project_sync/README.md delete mode 100644 roles/project_sync/defaults/main.yml delete mode 100644 roles/project_sync/meta/argument_specs.yml delete mode 100644 roles/project_sync/meta/main.yml delete mode 100644 roles/project_sync/tasks/main.yml delete mode 100644 roles/project_sync/tests/test.yml delete mode 100644 roles/project_sync/tests/vars/projects.yml diff --git a/README.md b/README.md index 4de2291..8c3208f 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ collections: ## Using this collection -You can make use of this collection by directly invoking the roles or modules using the FQCN (fully qualified collection name). +You can make use of this collection by directly invoking the roles using the FQCN (fully qualified collection name). In a playbook this might look like: @@ -67,18 +67,6 @@ In a playbook this might look like: - infra.eda_configuration.projects ``` -or - -```yaml -- name: Call Project role - hosts: localhost - tasks: - - name: Add a project - infra.eda_configuration.project: - name: my_project - url: https://github.com/my/project.git -``` - ### See Also - [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details. diff --git a/galaxy.yml b/galaxy.yml index 2479783..0a19a3d 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -4,7 +4,8 @@ authors: - Tom Page @Tompage1994 - Sean Sullivan @sean-m-sullivan - David Danielsson @djdanielsson -dependencies: {} +dependencies: + ansible.eda: ">=2.1.0" description: Ansible content that interacts with the Ansible EDA Controller. documentation: https://github.com/redhat-cop/eda_configuration/blob/devel/README.md license: diff --git a/plugins/doc_fragments/auth.py b/plugins/doc_fragments/auth.py deleted file mode 100644 index 6b354c3..0000000 --- a/plugins/doc_fragments/auth.py +++ /dev/null @@ -1,54 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright: (c) 2023, Chris Renwick <@crenwick93> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - - -class ModuleDocFragment(object): - - # Ansible Galaxy documentation fragment - DOCUMENTATION = r""" -options: - eda_host: - description: - - URL to Ansible Galaxy or EDA Controller instance. - - If value not set, will try environment variable C(EDA_HOST) - - If value not specified by any means, the value of C(127.0.0.1) will be used - type: str - aliases: [ eda_hostname ] - eda_username: - description: - - Username for your Ansible Galaxy or EDA Controller instance. - - If value not set, will try environment variable C(EDA_USERNAME) - type: str - eda_password: - description: - - Password for your Ansible Galaxy or EDA Controller instance. - - If value not set, will try environment variable C(EDA_PASSWORD) - type: str - eda_token: - description: - - The Ansible Galaxy or EDA Controller API token to use. - - This value can be in one of two formats. - - A string which is the token itself. (i.e. bqV5txm97wqJqtkxlMkhQz0pKhRMMX) - - A dictionary structure as returned by the eda_token module. - - If value not set, will try environment variable C(EDA_API_TOKEN) - type: raw - validate_certs: - description: - - Whether to allow insecure connections to Galaxy or EDA Controller Server. - - If C(no), SSL certificates will not be validated. - - This should only be used on personally controlled sites using self-signed certificates. - - If value not set, will try environment variable C(EDA_VERIFY_SSL) - type: bool - aliases: [ eda_verify_ssl ] - request_timeout: - description: - - Specify the timeout Ansible should use in requests to the Galaxy or EDA Controller host. - - Defaults to 10s, but this is handled by the shared module_utils code - type: float -""" diff --git a/plugins/doc_fragments/auth_plugin.py b/plugins/doc_fragments/auth_plugin.py deleted file mode 100644 index bf09ef3..0000000 --- a/plugins/doc_fragments/auth_plugin.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright: (c) 2020, Ansible by Red Hat, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - - -class ModuleDocFragment(object): - - # Automation Platform EDA Controller documentation fragment - DOCUMENTATION = r""" -options: - host: - description: The network address of your EDA Controller host. - env: - - name: EDA_HOST - username: - description: The user that you plan to use to access EDA Controller. - env: - - name: EDA_USERNAME - password: - description: The password for your EDA Controller user. - env: - - name: EDA_PASSWORD - request_timeout: - description: - - Specify the timeout Ansible should use in requests to the EDA Controller host. - - Defaults to 10 seconds - type: float - env: - - name: EDA_REQUEST_TIMEOUT - verify_ssl: - description: - - Specify whether Ansible should verify the SSL certificate of the EDA Controller host. - - Defaults to True, but this is handled by the shared module_utils code - type: bool - env: - - name: EDA_VERIFY_SSL - aliases: [ validate_certs ] -""" diff --git a/plugins/lookup/eda_api.py b/plugins/lookup/eda_api.py deleted file mode 100644 index 3710a3b..0000000 --- a/plugins/lookup/eda_api.py +++ /dev/null @@ -1,160 +0,0 @@ -# (c) 2020 Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - -DOCUMENTATION = """ -name: eda_api -author: Tom Page (@Tompage1994) -short_description: Search the API for objects -requirements: - - None -description: - - Returns GET requests from the EDA Controller API. -options: - _terms: - description: - - The endpoint to query, i.e. credentials, decision_environments, projects, etc. - required: True - query_params: - description: - - The query parameters to search for in the form of key/value pairs. - type: dict - required: False - aliases: [query, data, filter, params] - expect_objects: - description: - - Error if the response does not contain either a detail view or a list view. - type: boolean - default: False - aliases: [expect_object] - expect_one: - description: - - Error if the response contains more than one object. - type: boolean - default: False - return_objects: - description: - - If a list view is returned, promote the list of data to the top-level of list returned. - - Allows using this lookup plugin to loop over objects without additional work. - type: boolean - default: True - return_all: - description: - - If the response is paginated, return all pages. - type: boolean - default: False - return_ids: - description: - - If response contains objects, promote the id key to the top-level entries in the list. - - Allows looking up a related object and passing it as a parameter to another module. - - This will convert the return to a string or list of strings depending on the number of selected items. - type: boolean - aliases: [return_id] - default: False - max_objects: - description: - - if C(return_all) is true, this is the maximum of number of objects to return from the list. - - If a list view returns more an max_objects an exception will be raised - type: integer - default: 1000 -extends_documentation_fragment: infra.eda_configuration.auth_plugin -notes: - - If the query is not filtered properly this can cause a performance impact. -""" - -EXAMPLES = """ -- name: Report the usernames of all users - debug: - msg: "Users: {{ query('infra.eda_configuration.eda_api', 'users', return_all=true) | map(attribute='username') | list }}" - -- name: List all projects which use the ansible/eda github repo - debug: - msg: "{{ lookup('infra.eda_configuration.eda_api', 'project', host='https://eda.example.com', username='ansible', - password='Passw0rd123', verify_ssl=false, query_params={'url': 'https://github.com/ansible/event-driven-ansible.git'}) }}" -""" - -RETURN = """ -_raw: - description: - - Response from the API - type: dict - returned: on successful request -""" - -from ansible.plugins.lookup import LookupBase -from ansible.errors import AnsibleError -from ansible.module_utils._text import to_native -from ansible.utils.display import Display -from ..module_utils.eda_module import EDAModule - - -display = Display() - - -class LookupModule(LookupBase): - def handle_error(self, **kwargs): - raise AnsibleError(to_native(kwargs.get('msg'))) - - def warn_callback(self, warning): - self.display.warning(warning) - - def run(self, terms, variables=None, **kwargs): - if len(terms) != 1: - raise AnsibleError('You must pass exactly one endpoint to query') - - self.set_options(direct=kwargs) - - # Defer processing of params to logic shared with the modules - module_params = {} - for plugin_param, module_param in EDAModule.short_params.items(): - opt_val = self.get_option(plugin_param) - if opt_val is not None: - module_params[module_param] = opt_val - - # Create our module - module = EDAModule(argument_spec={}, direct_params=module_params, error_callback=self.handle_error, warn_callback=self.warn_callback) - - response = module.get_endpoint(terms[0], data=self.get_option('query_params', {})) - - if 'status_code' not in response: - raise AnsibleError("Unclear response from API: {0}".format(response)) - - if response['status_code'] != 200: - raise AnsibleError("Failed to query the API: {0}".format(response['json'].get('detail', response['json']))) - - return_data = response['json'] - - if self.get_option('expect_objects') or self.get_option('expect_one'): - if ('id' not in return_data) and ('results' not in return_data): - raise AnsibleError('Did not obtain a list or detail view at {0}, and ' 'expect_objects or expect_one is set to True'.format(terms[0])) - - if self.get_option('expect_one'): - if 'results' in return_data and len(return_data['results']) != 1: - raise AnsibleError('Expected one object from endpoint {0}, ' 'but obtained {1} from API'.format(terms[0], len(return_data['results']))) - - if self.get_option('return_all') and 'results' in return_data: - if return_data['count'] > self.get_option('max_objects'): - raise AnsibleError( - 'List view at {0} returned {1} objects, which is more than the maximum allowed ' - 'by max_objects, {2}'.format(terms[0], return_data['count'], self.get_option('max_objects')) - ) - - next_page = return_data['next'] - while next_page is not None: - next_response = module.get_endpoint(next_page) - return_data['results'] += next_response['json']['results'] - next_page = next_response['json']['next'] - return_data['next'] = None - - if self.get_option('return_ids'): - if 'results' in return_data: - return_data['results'] = [str(item['id']) for item in return_data['results']] - elif 'id' in return_data: - return_data = str(return_data['id']) - - if self.get_option('return_objects') and 'results' in return_data: - return return_data['results'] - else: - return [return_data] diff --git a/plugins/module_utils/eda_module.py b/plugins/module_utils/eda_module.py deleted file mode 100644 index 138000e..0000000 --- a/plugins/module_utils/eda_module.py +++ /dev/null @@ -1,904 +0,0 @@ -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - -from ansible.module_utils.basic import AnsibleModule, env_fallback -from ansible.module_utils.urls import ( - Request, - SSLValidationError, - ConnectionError, -) -from ansible.module_utils.six import PY2 -from ansible.module_utils.six.moves.urllib.parse import urlparse, urlencode -from ansible.module_utils.six.moves.urllib.error import HTTPError -from ansible.module_utils.six.moves.http_cookiejar import CookieJar -import os.path -from socket import gethostbyname -import re -from json import loads, dumps -import base64 -import os -import time - - -class ItemNotDefined(Exception): - pass - - -class EDAModule(AnsibleModule): - url = None - session = None - AUTH_ARGSPEC = dict( - eda_host=dict( - required=False, - aliases=["eda_hostname"], - fallback=(env_fallback, ["EDA_HOST"]), - ), - eda_username=dict(required=False, fallback=(env_fallback, ["EDA_USERNAME"])), - eda_password=dict(no_log=True, required=False, fallback=(env_fallback, ["EDA_PASSWORD"])), - validate_certs=dict( - type="bool", - aliases=["eda_verify_ssl"], - required=False, - fallback=(env_fallback, ["EDA_VERIFY_SSL"]), - ), - eda_token=dict( - type="raw", - no_log=True, - required=False, - fallback=(env_fallback, ["EDA_API_TOKEN"]), - ), - request_timeout=dict( - type="float", - required=False, - fallback=(env_fallback, ["EDA_REQUEST_TIMEOUT"]) - ), - ) - ENCRYPTED_STRING = "$encrypted$" - short_params = { - "host": "eda_host", - "username": "eda_username", - "password": "eda_password", - "verify_ssl": "validate_certs", - "request_timeout": "request_timeout", - } - IDENTITY_FIELDS = {"users": "username"} - ENCRYPTED_STRING = "$encrypted$" - host = "127.0.0.1" - username = None - password = None - verify_ssl = True - request_timeout = 10 - basic_auth = True - authenticated = False - error_callback = None - warn_callback = None - - def __init__(self, argument_spec=None, direct_params=None, error_callback=None, warn_callback=None, require_auth=True, **kwargs): - full_argspec = {} - if require_auth: - full_argspec.update(EDAModule.AUTH_ARGSPEC) - full_argspec.update(argument_spec) - kwargs["supports_check_mode"] = True - - self.error_callback = error_callback - self.warn_callback = warn_callback - - self.json_output = {"changed": False} - - if direct_params is not None: - self.params = direct_params - else: - super(EDAModule, self).__init__(argument_spec=full_argspec, **kwargs) - - self.session = Request(cookies=CookieJar(), validate_certs=self.verify_ssl, timeout=self.request_timeout) - - # Parameters specified on command line will override settings in any config - for short_param, long_param in self.short_params.items(): - direct_value = self.params.get(long_param) - if direct_value is not None: - setattr(self, short_param, direct_value) - - # Perform some basic validation - if not re.match("^https{0,1}://", self.host): - self.host = "https://{0}".format(self.host) - - # Try to parse the hostname as a url - try: - self.url = urlparse(self.host) - except Exception as e: - self.fail_json(msg="Unable to parse eda host as a URL ({1}): {0}".format(self.host, e)) - - # Try to resolve the hostname - hostname = self.url.netloc.split(":")[0] - try: - gethostbyname(hostname) - except Exception as e: - self.fail_json(msg="Unable to resolve eda host ({1}): {0}".format(hostname, e)) - - if "update_secrets" in self.params: - self.update_secrets = self.params.pop("update_secrets") - else: - self.update_secrets = True - - def build_url(self, endpoint, query_params=None): - # Make sure we start with /api/vX - if not endpoint.startswith("/"): - endpoint = "/{0}".format(endpoint) - if not endpoint.startswith("/api/"): - endpoint = "api/eda/v1{0}".format(endpoint) - if not endpoint.endswith("/") and "?" not in endpoint: - endpoint = "{0}/".format(endpoint) - - # Update the URL path with the endpoint - url = self.url._replace(path=endpoint) - - if query_params: - url = url._replace(query=urlencode(query_params)) - - return url - - def fail_json(self, **kwargs): - # Try to log out if we are authenticated - if self.error_callback: - self.error_callback(**kwargs) - else: - super(EDAModule, self).fail_json(**kwargs) - - def exit_json(self, **kwargs): - # Try to log out if we are authenticated - super(EDAModule, self).exit_json(**kwargs) - - def warn(self, warning): - if self.warn_callback is not None: - self.warn_callback(warning) - else: - super(EDAModule, self).warn(warning) - - @staticmethod - def get_name_field_from_endpoint(endpoint): - return EDAModule.IDENTITY_FIELDS.get(endpoint, "name") - - def get_endpoint(self, endpoint, *args, **kwargs): - return self.make_request("GET", endpoint, **kwargs) - - def make_request(self, method, endpoint, *args, **kwargs): - # In case someone is calling us directly; make sure we were given a method, let's not just assume a GET - if not method: - raise Exception("The HTTP method must be defined") - - # Extract the headers, this will be used in a couple of places - headers = kwargs.get("headers", {}) - - # Authenticate to EDA controller (if we don't have a token and if not already done so) - if not self.authenticated: - self.authenticate(**kwargs) - if self.basic_auth: - basic_str = base64.b64encode("{0}:{1}".format(self.username, self.password).encode("ascii")) - headers["Authorization"] = "Basic {0}".format(basic_str.decode("ascii")) - if method in ["POST", "PUT", "PATCH"]: - headers.setdefault("Content-Type", "application/json") - kwargs["headers"] = headers - url = self.build_url(endpoint) - else: - url = self.build_url(endpoint, query_params=kwargs.get("data")) - - data = None # Important, if content type is not JSON, this should not be dict type - if headers.get("Content-Type", "") == "application/json": - data = dumps(kwargs.get("data", {})) - elif kwargs.get("binary", False): - data = kwargs.get("data", None) - - try: - response = self.session.open( - method, - url.geturl(), - headers=headers, - validate_certs=self.verify_ssl, - timeout=self.request_timeout, - follow_redirects=True, - data=data, - ) - except (SSLValidationError) as ssl_err: - self.fail_json(msg="Could not establish a secure connection to your host ({1}): {0}.".format(url.netloc, ssl_err)) - except (ConnectionError) as con_err: - self.fail_json(msg="There was a network error of some kind trying to connect to your host ({1}): {0}.".format(url.netloc, con_err)) - except (HTTPError) as he: - # Sanity check: Did the server send back some kind of internal error? - if he.code >= 500: - self.fail_json(msg="The host sent back a server error ({1}): {0}. Please check the logs and try again later".format(url.path, he)) - # Sanity check: Did we fail to authenticate properly? If so, fail out now; this is always a failure. - elif he.code == 401: - self.fail_json(msg="Invalid EDA Controller authentication credentials for {0} (HTTP 401).".format(url.path)) - # Sanity check: Did we get a forbidden response, which means that the user isn't allowed to do this? Report that. - elif he.code == 403: - self.fail_json(msg="You don't have permission to {1} to {0} (HTTP 403).".format(url.path, method)) - # Sanity check: Did we get a 404 response? - # Requests with primary keys will return a 404 if there is no response, and we want to consistently trap these. - elif he.code == 404: - if kwargs.get("return_none_on_404", False): - return None - if kwargs.get("return_errors_on_404", False): - page_data = he.read() - try: - return {"status_code": he.code, "json": loads(page_data)} - # JSONDecodeError only available on Python 3.5+ - except ValueError: - return {"status_code": he.code, "text": page_data} - self.fail_json( - msg="The requested object could not be found at {0}.".format(url.path), - response=he, - ) - # Sanity check: Did we get a 405 response? - # A 405 means we used a method that isn't allowed. Usually this is a bad request, but it requires special treatment because the - # API sends it as a logic error in a few situations (e.g. trying to cancel a job that isn't running). - elif he.code == 405: - self.fail_json(msg="The EDA Controller server says you can't make a request with the {0} method to this endpoint {1}".format(method, url.path)) - # Sanity check: Did we get some other kind of error? If so, write an appropriate error message. - elif he.code >= 400: - # We are going to return a 400 so the module can decide what to do with it - page_data = he.read() - try: - return {"status_code": he.code, "json": loads(page_data)} - # JSONDecodeError only available on Python 3.5+ - except ValueError: - return {"status_code": he.code, "text": page_data} - elif he.code == 204 and method == "DELETE": - # A 204 is a normal response for a delete function - pass - else: - self.fail_json(msg="Unexpected return code when calling {0}: {1}".format(url.geturl(), he)) - except (Exception) as e: - self.fail_json(msg="There was an unknown error when trying to connect to {2}: {0} {1}".format(type(e).__name__, e, url.geturl())) - - response_body = "" - try: - response_body = response.read() - except (Exception) as e: - self.fail_json(msg="Failed to read response body: {0}".format(e)) - - response_json = {} - if response_body and response_body != "": - try: - response_json = loads(response_body) - except (Exception) as e: - self.fail_json(msg="Failed to parse the response json: {0}".format(e)) - - if PY2: - status_code = response.getcode() - else: - status_code = response.status - return {"status_code": status_code, "json": response_json} - - def get_one(self, endpoint, name_or_id=None, allow_none=True, key="url", **kwargs): - new_kwargs = kwargs.copy() - if name_or_id: - name_field = self.get_name_field_from_endpoint(endpoint) - new_data = kwargs.get("data", {}).copy() - if name_field in new_data: - self.fail_json(msg="You can't specify the field {0} in your search data if using the name_or_id field".format(name_field)) - - try: - new_data["or__id"] = int(name_or_id) - new_data["or__{0}".format(name_field)] = name_or_id - except ValueError: - # If we get a value error, then we didn't have an integer so we can just pass and fall down to the fail - new_data[name_field] = name_or_id - new_kwargs["data"] = new_data - - response = self.get_endpoint(endpoint, **new_kwargs) - if response["status_code"] != 200: - fail_msg = "Got a {0} response when trying to get one from {1}".format(response["status_code"], endpoint) - if "detail" in response.get("json", {}): - fail_msg += ", detail: {0}".format(response["json"]["detail"]) - self.fail_json(msg=fail_msg) - - if "count" not in response["json"] or "results" not in response["json"]: - self.fail_json(msg="The endpoint did not provide count and results.") - - if response["json"]["count"] == 0: - if allow_none: - return None - else: - self.fail_wanted_one(response, endpoint, new_kwargs.get("data")) - elif response["json"]["count"] > 1: - if name_or_id: - # Since we did a name or ID search and got > 1 return something if the id matches or the name matches exactly - exact_matches = [] - for asset in response["json"]["results"]: - if str(asset["id"]) == name_or_id: - return self.existing_item_add_url(asset, endpoint, key=key) - if str(asset[name_field]) == name_or_id: - exact_matches.append(self.existing_item_add_url(asset, endpoint, key=key)) - # If there is one exact name match then return that - if len(exact_matches) == 1: - return exact_matches[0] - - # We got > 1 and either didn't find something by ID or exact name (which means multiple names) - # Or we weren't running with a or search and just got back too many to begin with. - if allow_none: - return None - else: - self.fail_wanted_one(response, endpoint, new_kwargs.get("data")) - else: - # Check if name actually matches and isn't just that we match part of the name - asset = response["json"]["results"][0] - if (str(asset["id"]) == name_or_id) or (str(asset[name_field]) == name_or_id): - return self.existing_item_add_url(response["json"]["results"][0], endpoint, key=key) - elif allow_none: - return None - else: - self.fail_wanted_one(response, endpoint, new_kwargs.get("data")) - - def get_by_id(self, endpoint, id, **kwargs): - new_kwargs = kwargs.copy() - - response = self.get_endpoint("{endpoint}/{id}".format(endpoint=endpoint, id=id), **new_kwargs) - if response["status_code"] != 200: - fail_msg = "Got a {0} response when trying to get id:{1} from {2}".format(response["status_code"], id, endpoint) - if "detail" in response.get("json", {}): - fail_msg += ", detail: {0}".format(response["json"]["detail"]) - self.fail_json(msg=fail_msg) - - return response["json"] - - def get_only(self, endpoint, name_or_id=None, allow_none=True, key="url", **kwargs): - new_kwargs = kwargs.copy() - if name_or_id: - name_field = self.get_name_field_from_endpoint(endpoint) - new_data = kwargs.get("data", {}).copy() - if name_field in new_data: - self.fail_json(msg="You can't specify the field {0} in your search data if using the name_or_id field".format(name_field)) - - try: - new_data["or__id"] = int(name_or_id) - new_data["or__{0}".format(name_field)] = name_or_id - except ValueError: - # If we get a value error, then we didn't have an integer so we can just pass and fall down to the fail - new_data[name_field] = name_or_id - new_kwargs["data"] = new_data - - response = self.get_endpoint(endpoint, **new_kwargs) - if response["status_code"] != 200: - fail_msg = "Got a {0} response when trying to get from {1}".format(response["status_code"], endpoint) - if "detail" in response.get("json", {}): - fail_msg += ", detail: {0}".format(response["json"]["detail"]) - self.fail_json(msg=fail_msg) - - return self.existing_item_add_url(response["json"], endpoint, key=key) - - def authenticate(self, **kwargs): - # Attempt to get a token from /auth/session/login by giving it our username/password combo - # If we have a username and password, we need to get a session cookie - - # Currently not implemented - # api_token_url = self.build_url("auth/session/login").geturl()[:-1] - - # If we have not managed to authenticate of these, then we can try un-authenticated access or use basic auth - self.authenticated = True - - def existing_item_add_url(self, existing_item, endpoint, key="url"): - # Add url and type to response as its missing in current iteration of EDA Controller. - existing_item[key] = "{0}{1}/".format(self.build_url(endpoint).geturl()[len(self.host):], existing_item["id"]) - existing_item["type"] = endpoint - return existing_item - - def delete_if_needed(self, existing_item, on_delete=None, auto_exit=True, key="url"): - # This will exit from the module on its own. - # If the method successfully deletes an item and on_delete param is defined, - # the on_delete parameter will be called as a method pasing in this object and the json from the response - # This will return one of two things: - # 1. None if the existing_item is not defined (so no delete needs to happen) - # 2. The response from EDA Controller from calling the delete on the endpont. It's up to you to process the response and exit from the module - # Note: common error codes from the EDA Controller API can cause the module to fail - if existing_item: - if existing_item["type"] == "token": - response = self.delete_endpoint(existing_item["endpoint"]) - else: - # If we have an item, we can try to delete it - try: - item_url = existing_item[key] - item_type = existing_item["type"] - item_id = existing_item["id"] - item_name = self.get_item_name(existing_item, allow_unknown=True) - except KeyError as ke: - self.fail_json(msg="Unable to process delete of item due to missing data {0}".format(ke)) - response = self.delete_endpoint(item_url) - else: - if auto_exit: - self.exit_json(**self.json_output) - else: - return self.json_output - - if response["status_code"] in [202, 204]: - if on_delete: - on_delete(self, response["json"]) - self.json_output["changed"] = True - if existing_item["type"] == "token": - self.json_output["msg"] = "Token Revoked" - self.exit_json(**self.json_output) - else: - self.json_output["id"] = item_id - self.exit_json(**self.json_output) - if auto_exit: - self.exit_json(**self.json_output) - else: - return self.json_output - else: - if "json" in response and "__all__" in response["json"]: - self.fail_json(msg="Unable to delete {0} {1}: {2}".format(item_type, item_name, response["json"]["__all__"][0])) - elif "json" in response: - # This is from a project delete (if there is an active job against it) - if "error" in response["json"]: - self.fail_json(msg="Unable to delete {0} {1}: {2}".format(item_type, item_name, response["json"]["error"])) - else: - self.fail_json(msg="Unable to delete {0} {1}: {2}".format(item_type, item_name, response["json"])) - else: - self.fail_json(msg="Unable to delete {0} {1}: {2}".format(item_type, item_name, response["status_code"])) - - def get_item_name(self, item, allow_unknown=False): - if item: - if "name" in item: - return item["name"] - - if allow_unknown: - return "unknown" - - if item: - self.exit_json(msg="Cannot determine identity field for {0} object.".format(item.get("type", "unknown"))) - else: - self.exit_json(msg="Cannot determine identity field for Undefined object.") - - def delete_endpoint(self, endpoint, *args, **kwargs): - # Handle check mode - if self.check_mode: - self.json_output["changed"] = True - self.exit_json(**self.json_output) - - return self.make_request("DELETE", endpoint, **kwargs) - - def create_or_update_if_needed( - self, - existing_item, - new_item, - endpoint=None, - item_type="unknown", - on_create=None, - on_update=None, - auto_exit=True, - associations=None, - require_id=True, - fixed_url=None, - key="url", - ): - if existing_item: - return self.update_if_needed( - existing_item, - new_item, - endpoint=endpoint, - on_update=on_update, - auto_exit=auto_exit, - associations=associations, - require_id=require_id, - fixed_url=fixed_url, - key=key, - ) - else: - return self.create_if_needed( - existing_item, - new_item, - endpoint, - on_create=on_create, - item_type=item_type, - auto_exit=auto_exit, - associations=associations, - ) - - def create_if_needed( - self, - existing_item, - new_item, - endpoint, - on_create=None, - auto_exit=True, - item_type="unknown", - associations=None, - treat_conflict_as_unchanged=False, - ): - - # This will exit from the module on its own - # If the method successfully creates an item and on_create param is defined, - # the on_create parameter will be called as a method pasing in this object and the json from the response - # This will return one of two things: - # 1. None if the existing_item is already defined (so no create needs to happen) - # 2. The response from EDA Controller from calling the patch on the endpont. It's up to you to process the response and exit from the module - # Note: common error codes from the EDA Controller API can cause the module to fail - - if not endpoint: - self.fail_json(msg="Unable to create new {0} due to missing endpoint".format(item_type)) - - item_url = None - if existing_item: - try: - item_url = existing_item["url"] - except KeyError as ke: - self.fail_json(msg="Unable to process create of item due to missing data {0}".format(ke)) - else: - # If we don't have an exisitng_item, we can try to create it - - # We have to rely on item_type being passed in since we don't have an existing item that declares its type - # We will pull the item_name out from the new_item, if it exists - item_name = self.get_item_name(new_item, allow_unknown=True) - - response = self.post_endpoint(endpoint, **{"data": new_item}) - - if response["status_code"] in [200, 201]: - self.json_output["name"] = "unknown" - for key in ("name", "username", "identifier", "hostname"): - if key in response["json"]: - self.json_output["name"] = response["json"][key] - if item_type != "token": - self.json_output["id"] = response["json"]["id"] - item_url = "{0}{1}/".format( - self.build_url(endpoint).geturl()[len(self.host):], - response["json"]["id"], - ) - self.json_output["changed"] = True - elif response["status_code"] in [409] and treat_conflict_as_unchanged: - self.json_output["changed"] = False - else: - if "json" in response and "__all__" in response["json"]: - self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, item_name, response["json"]["__all__"][0])) - elif "json" in response: - self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, item_name, response["json"])) - else: - self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, item_name, response["status_code"])) - - # Process any associations with this item - if associations is not None: - for association_type in associations: - sub_endpoint = "{0}{1}/".format(item_url, association_type) - self.modify_associations(sub_endpoint, associations[association_type]) - - # If we have an on_create method and we actually changed something we can call on_create - if on_create is not None and self.json_output["changed"]: - on_create(self, response["json"]) - elif auto_exit: - self.exit_json(**self.json_output) - else: - last_data = response["json"] - return last_data - - def create_no_name( - self, - new_item, - endpoint, - on_create=None, - auto_exit=False, - item_type="unknown", - ): - - # This will exit from the module on its own - # If the method successfully creates an item and on_create param is defined, - # the on_create parameter will be called as a method pasing in this object and the json from the response - # This will return one of two things: - # 1. None if the existing_item is already defined (so no create needs to happen) - # 2. The response from EDA Controller from calling the patch on the endpont. It's up to you to process the response and exit from the module - # Note: common error codes from the EDA Controller API can cause the module to fail - - if not endpoint: - self.fail_json(msg="Unable to create new {0} due to missing endpoint".format(item_type)) - - # We have to rely on item_type being passed in since we don't have an existing item that declares its type - # We will pull the item_name out from the new_item, if it exists - - response = self.post_endpoint(endpoint, **{"data": new_item}) - - if response["status_code"] in [200, 201]: - self.json_output["changed"] = True - else: - if "json" in response and "__all__" in response["json"]: - self.fail_json(msg="Unable to create {0}: {1}".format(item_type, response["json"]["__all__"][0])) - elif "json" in response: - self.fail_json(msg="Unable to create {0}: {1}".format(item_type, response["json"])) - else: - self.fail_json(msg="Unable to create {0}: {1}".format(item_type, response["status_code"])) - - # If we have an on_create method and we actually changed something we can call on_create - if on_create is not None and self.json_output["changed"]: - on_create(self, response["json"]) - elif auto_exit: - self.exit_json(**self.json_output) - else: - last_data = response["json"] - return last_data - - def update_if_needed( - self, - existing_item, - new_item, - endpoint, - on_update=None, - auto_exit=True, - associations=None, - require_id=True, - fixed_url=None, - key="url", - ): - # This will exit from the module on its own - # If the method successfully updates an item and on_update param is defined, - # the on_update parameter will be called as a method pasing in this object and the json from the response - # This will return one of two things: - # 1. None if the existing_item does not need to be updated - # 2. The response from EDA Controller from patching to the endpoint. It's up to you to process the response and exit from the module. - # Note: common error codes from the EDA Controller API can cause the module to fail - response = None - if existing_item: - # If we have an item, we can see if it needs an update - try: - item_url = fixed_url or existing_item[key] - item_type = existing_item["type"] - name_field = self.get_name_field_from_endpoint(endpoint) - item_name = existing_item[name_field] - item_id = require_id and existing_item["id"] - except KeyError as ke: - self.fail_json(msg="Unable to process update of item due to missing data {0}".format(ke)) - - # Check to see if anything within the item requires the item to be updated - needs_patch = self.objects_could_be_different(existing_item, new_item) - - # If we decided the item needs to be updated, update it - self.json_output["id"] = item_id - self.json_output["name"] = item_name - self.json_output["type"] = item_type - if needs_patch: - response = self.patch_endpoint(item_url, **{"data": new_item}) - if response["status_code"] == 200: - # compare apples-to-apples, old API data to new API data - # but do so considering the fields given in parameters - self.json_output["changed"] = self.objects_could_be_different( - existing_item, - response["json"], - field_set=new_item.keys(), - warning=True, - ) - elif "json" in response and "__all__" in response["json"]: - self.fail_json(msg=response["json"]["__all__"]) - else: - self.fail_json( - **{ - "msg": "Unable to update {0} {1}, see response".format(item_type, item_name), - "response": response, - "input": new_item, - } - ) - - else: - raise RuntimeError("update_if_needed called incorrectly without existing_item") - - # Process any associations with this item - if associations is not None: - for association_type, id_list in associations.items(): - endpoint = "{0}{1}/".format(item_url, association_type) - self.modify_associations(endpoint, id_list) - - # If we change something and have an on_change call it - if on_update is not None and self.json_output["changed"]: - if response is None: - last_data = existing_item - else: - last_data = response["json"] - on_update(self, last_data) - elif auto_exit: - self.exit_json(**self.json_output) - else: - if response is None: - last_data = existing_item - else: - last_data = response["json"] - return last_data - - def modify_associations(self, association_endpoint, new_association_list): - # if we got None instead of [] we are not modifying the association_list - if new_association_list is None: - return - - # First get the existing associations - response = self.get_all_endpoint(association_endpoint) - existing_associated_ids = [association["id"] for association in response["json"]["results"]] - - # Disassociate anything that is in existing_associated_ids but not in new_association_list - ids_to_remove = list(set(existing_associated_ids) - set(new_association_list)) - for an_id in ids_to_remove: - response = self.post_endpoint(association_endpoint, **{"data": {"id": int(an_id), "disassociate": True}}) - if response["status_code"] == 204: - self.json_output["changed"] = True - else: - self.fail_json(msg="Failed to disassociate item {0}".format(response["json"].get("detail", response["json"]))) - - # Associate anything that is in new_association_list but not in `association` - for an_id in list(set(new_association_list) - set(existing_associated_ids)): - response = self.post_endpoint(association_endpoint, **{"data": {"id": int(an_id)}}) - if response["status_code"] == 204: - self.json_output["changed"] = True - else: - self.fail_json(msg="Failed to associate item {0}".format(response["json"].get("detail", response["json"]))) - - def post_endpoint(self, endpoint, *args, **kwargs): - # Handle check mode - if self.check_mode: - self.json_output["changed"] = True - self.exit_json(**self.json_output) - - return self.make_request("POST", endpoint, **kwargs) - - def patch_endpoint(self, endpoint, *args, **kwargs): - # Handle check mode - if self.check_mode: - self.json_output["changed"] = True - self.exit_json(**self.json_output) - - return self.make_request("PATCH", endpoint, **kwargs) - - def put_endpoint(self, endpoint, *args, **kwargs): - # Handle check mode - if self.check_mode: - self.json_output["changed"] = True - self.exit_json(**self.json_output) - - return self.make_request("PUT", endpoint, **kwargs) - - def get_all_endpoint(self, endpoint, *args, **kwargs): - response = self.get_endpoint(endpoint, *args, **kwargs) - if "next" not in response["json"]: - raise RuntimeError("Expected list from API at {0}, got: {1}".format(endpoint, response)) - next_page = response["json"]["next"] - - if response["json"]["count"] > 10000: - self.fail_json(msg="The number of items being queried for is higher than 10,000.") - - while next_page is not None: - next_response = self.get_endpoint(next_page) - response["json"]["results"] = response["json"]["results"] + next_response["json"]["results"] - next_page = next_response["json"]["next"] - response["json"]["next"] = next_page - return response - - def fail_wanted_one(self, response, endpoint, query_params): - sample = response.copy() - if len(sample["json"]["results"]) > 1: - sample["json"]["results"] = sample["json"]["results"][:2] + ["...more results snipped..."] - url = self.build_url(endpoint, query_params) - display_endpoint = url.geturl()[len(self.host):] # truncate to not include the base URL - self.fail_json( - msg="Request to {0} returned {1} items, expected 1".format(display_endpoint, response["json"]["count"]), - query=query_params, - response=sample, - total_results=response["json"]["count"], - ) - - def get_exactly_one(self, endpoint, name_or_id=None, **kwargs): - return self.get_one(endpoint, name_or_id=name_or_id, allow_none=False, **kwargs) - - def resolve_name_to_id(self, endpoint, name_or_id, data=None): - return self.get_exactly_one(endpoint, name_or_id, **{"data": data if data else {}})["id"] - - def objects_could_be_different(self, old, new, field_set=None, warning=False): - if field_set is None: - field_set = set(fd for fd in new.keys() if fd not in ("modified", "related", "summary_fields")) - for field in field_set: - new_field = new.get(field, None) - old_field = old.get(field, None) - if old_field != new_field: - if self.update_secrets: - return True # Something doesn't match, or something might not match - elif self.has_encrypted_values(new_field) or field not in new: - if self.update_secrets: - # case of 'field not in new' - user password write-only field that API will not display - self._encrypted_changed_warning(field, old, warning=warning) - return True - return False - - def sync_project(self, id, wait=True, interval=1, timeout=None): - self.json_output["id"] = id - - # If the state was present and we can let the module build or update the existing item, this will return on its own - response = self.post_endpoint('projects/{id}/sync'.format(id=id)) - - if response["status_code"] == 202: - if wait: - status = None - start = time.time() - elapsed = 0 - while status != "completed" and status != "failed": - project = self.get_endpoint('projects/{id}'.format(id=id))["json"] - self.json_output["project"] = project - status = project["import_state"] - time.sleep(interval) - elapsed = time.time() - start - if timeout and elapsed > timeout: - self.fail_json(msg="Timed out awaiting task completion.", project=project) - if status == "failed": - self.fail_json(msg="The project sync failed", task=project["import_error"]) - else: - if "json" in response and "__all__" in response["json"]: - if "detail" in response["json"]["__all__"][0] and response["json"]["__all__"][0]["detail"] == "Project import or sync is already running.": - self.json_output["changed"] = False - self.json_output["detail"] = response["json"]["__all__"][0]["detail"] - self.exit_json(**self.json_output) - else: - self.fail_json(msg="Unable to sync project: {0}".format(response["json"]["__all__"][0])) - elif "json" in response: - # This is from a project delete (if there is an active job against it) - if "error" in response["json"]: - if "detail" in response["json"]["error"] and response["json"]["error"]["detail"] == "Project import or sync is already running.": - self.json_output["changed"] = False - self.json_output["detail"] = response["json"]["error"]["detail"] - self.exit_json(**self.json_output) - else: - self.fail_json(msg="Unable to sync project: {0}".format(response["json"]["error"])) - else: - self.fail_json(msg="Unable to sync project: {0}".format(response["json"])) - else: - self.fail_json(msg="Unable to sync project: {0}".format(response["status_code"])) - - self.json_output["changed"] = True - self.exit_json(**self.json_output) - - def trigger_post_action( - self, - endpoint, - auto_exit=False, - data=None, - ): - - if not endpoint: - self.fail_json(msg="Unable to trigger action due to missing endpoint") - - response = self.post_endpoint(endpoint, **{"data": data}) - - if response["status_code"] in [200, 201, 204]: - self.json_output["changed"] = True - else: - if "json" in response and "__all__" in response["json"]: - self.fail_json(msg="Unable to trigger {0}: {1}".format(endpoint, response["json"]["__all__"][0])) - elif "json" in response: - self.fail_json(msg="Unable to trigger {0}: {1}".format(endpoint, response["json"])) - else: - self.fail_json(msg="Unable to trigger {0}: {1}".format(endpoint, response["status_code"])) - - if auto_exit: - self.exit_json(**self.json_output) - else: - last_data = response["json"] - return last_data - - @staticmethod - def _resolve_path(path): - return os.path.abspath(os.path.expanduser(os.path.expandvars(path))) - - @staticmethod - def has_encrypted_values(obj): - """Returns True if JSON-like python content in obj has $encrypted$ - anywhere in the data as a value - """ - if isinstance(obj, dict): - for val in obj.values(): - if EDAModule.has_encrypted_values(val): - return True - elif isinstance(obj, list): - for val in obj: - if EDAModule.has_encrypted_values(val): - return True - elif obj == EDAModule.ENCRYPTED_STRING: - return True - return False - - def _encrypted_changed_warning(self, field, old, warning=False): - if not warning: - return - self.warn( - "The field {0} of {1} {2} has encrypted data and may inaccurately report task is changed.".format( - field, old.get("type", "unknown"), old.get("id", "unknown") - ) - ) diff --git a/plugins/modules/__init__.py b/plugins/modules/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/plugins/modules/credential.py b/plugins/modules/credential.py deleted file mode 100644 index cbcb3fe..0000000 --- a/plugins/modules/credential.py +++ /dev/null @@ -1,143 +0,0 @@ -#!/usr/bin/python -# coding: utf-8 -*- - -# (c) 2024, Derek Waters -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["preview"], - "supported_by": "community", -} - - -DOCUMENTATION = """ ---- -module: credential -author: "Derek Waters (@derekwaters)" -short_description: Manage a Credential in EDA Controller -description: - - Create, update and delete credentials in EDA Controller -options: - name: - description: - - The name of the credential. - required: True - type: str - new_name: - description: - - Setting this option will change the existing name (looked up via the name field). - type: str - description: - description: - - The description of the credential. - required: False - type: str - username: - description: - - The username used to access the project repository. - required: True - type: str - secret: - description: - - The secret associated with the credential (either a password or access token). - required: True - type: str - credential_type: - description: - - The type of the credential. - choices: ["GitHub Personal Access Token", "GitLab Personal Access Token", "Container Registry"] - default: "GitHub Personal Access Token" - type: str - state: - description: - - Desired state of the resource. - choices: ["present", "absent"] - default: "present" - type: str - -extends_documentation_fragment: infra.eda_configuration.auth -""" - - -EXAMPLES = """ -- name: Create eda credential - infra.eda_configuration.credential: - name: my_credential - description: my github access credential - username: derekwaters - secret: this_is_not_a_real_token - credential_type: "GitHub Personal Access Token" - state: present - eda_host: eda.example.com - eda_username: admin - eda_password: Sup3r53cr3t - -""" - -from ..module_utils.eda_module import EDAModule - - -def main(): - # Any additional arguments that are not fields of the item can be added here - argument_spec = dict( - name=dict(required=True), - new_name=dict(), - description=dict(), - username=dict(required=True), - secret=dict(required=True, no_log=True), - credential_type=dict(choices=["GitHub Personal Access Token", - "GitLab Personal Access Token", - "Container Registry"], - default="GitHub Personal Access Token"), - state=dict(choices=["present", "absent"], default="present"), - ) - - # Create a module for ourselves - module = EDAModule(argument_spec=argument_spec) - - # Extract our parameters - name = module.params.get("name") - new_name = module.params.get("new_name") - state = module.params.get("state") - - new_fields = {} - - # Attempt to look up an existing item based on the provided data - existing_item = module.get_one("credentials", name_or_id=name, key="req_url") - - if state == "absent": - # If the state was absent we can let the module delete it if needed, the module will handle exiting from this - module.delete_if_needed(existing_item, key="req_url") - - # Create the data that gets sent for create and update - # Remove these two comments for final - # Check that Links and groups works with this. - new_fields["name"] = new_name if new_name else (module.get_item_name(existing_item) if existing_item else name) - for field_name in ( - "description", - "credential_type", - "username", - "secret", - ): - field_val = module.params.get(field_name) - if field_val is not None: - new_fields[field_name] = field_val - - # If the state was present and we can let the module build or update the existing item, this will return on its own - module.create_or_update_if_needed( - existing_item, - new_fields, - endpoint="credentials", - item_type="credentials", - key="req_url", - ) - - -if __name__ == "__main__": - main() diff --git a/plugins/modules/decision_environment.py b/plugins/modules/decision_environment.py deleted file mode 100644 index bcb038f..0000000 --- a/plugins/modules/decision_environment.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/python -# coding: utf-8 -*- - -# (c) 2024, Derek Waters -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["preview"], - "supported_by": "community", -} - - -DOCUMENTATION = """ ---- -module: decision_environment -author: "Derek Waters (@derekwaters)" -short_description: Manage a Decision Environment in EDA Controller -description: - - Create, update and delete decision environments in EDA Controller -options: - name: - description: - - The name of the decision environment. - required: True - type: str - new_name: - description: - - Setting this option will change the existing name (looked up via the name field). - type: str - description: - description: - - The description of the decision environment. - required: False - type: str - image_url: - description: - - The full image location to use for the decision environment, including the container registry, image name, and version tag. - required: True - type: str - credential: - description: - - The token needed to access the container registry, if required. - required: False - type: str - state: - description: - - Desired state of the resource. - choices: ["present", "absent"] - default: "present" - type: str - -extends_documentation_fragment: infra.eda_configuration.auth -""" - - -EXAMPLES = """ -- name: Create eda decision environment - infra.eda_configuration.decision_environment: - name: my_de - description: my awesome decision environment - image_url: my-container_registry/ansible/de-minimal-8:latest - credential: registry_access_token - state: present - eda_host: eda.example.com - eda_username: admin - eda_password: Sup3r53cr3t - -""" - -from ..module_utils.eda_module import EDAModule - - -def main(): - # Any additional arguments that are not fields of the item can be added here - argument_spec = dict( - name=dict(required=True), - new_name=dict(), - description=dict(), - image_url=dict(required=True), - credential=dict(), - state=dict(choices=["present", "absent"], default="present"), - ) - - # Create a module for ourselves - module = EDAModule(argument_spec=argument_spec) - - # Extract our parameters - name = module.params.get("name") - new_name = module.params.get("new_name") - state = module.params.get("state") - - new_fields = {} - - # Attempt to look up an existing item based on the provided data - existing_item = module.get_one("decision-environments", name_or_id=name, key="req_url") - - if state == "absent": - # If the state was absent we can let the module delete it if needed, the module will handle exiting from this - module.delete_if_needed(existing_item, key="req_url") - - # Create the data that gets sent for create and update - # Remove these two comments for final - # Check that Links and groups works with this. - new_fields["name"] = new_name if new_name else (module.get_item_name(existing_item) if existing_item else name) - for field_name in ( - "description", - "image_url", - ): - field_val = module.params.get(field_name) - if field_val is not None: - new_fields[field_name] = field_val - - if module.params.get("credential") is not None: - new_fields["credential_id"] = module.resolve_name_to_id("credentials", module.params.get("credential")) - - # If the state was present and we can let the module build or update the existing item, this will return on its own - module.create_or_update_if_needed( - existing_item, - new_fields, - endpoint="decision-environments", - item_type="decision-environments", - key="req_url", - ) - - -if __name__ == "__main__": - main() diff --git a/plugins/modules/project.py b/plugins/modules/project.py deleted file mode 100644 index 8b061e3..0000000 --- a/plugins/modules/project.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/python -# coding: utf-8 -*- - -# (c) 2023, Chris Renwick <@crenwick93> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["preview"], - "supported_by": "community", -} - - -DOCUMENTATION = """ ---- -module: project -author: "Chris Renwick (@crenwick93)" -short_description: Manage a project in EDA Controller -description: - - Create, update and delete projects in EDA Controller -options: - name: - description: - - The name of the project. - required: True - type: str - new_name: - description: - - Setting this option will change the existing name (looked up via the name field). - type: str - description: - description: - - The description of the project. - required: False - type: str - url: - description: - - A URL to a remote archive, such as a Github Release or a build artifact stored in Artifactory and unpacks it into the project path for use. - required: True - type: str - aliases: ['scm_url'] - tls_validation: - description: - - Whether to use TLS validation against the url. - type: bool - default: True - credential: - description: - - The token needed to utilize the SCM URL. - required: False - type: str - state: - description: - - Desired state of the resource. - choices: ["present", "absent"] - default: "present" - type: str - -extends_documentation_fragment: infra.eda_configuration.auth -""" - - -EXAMPLES = """ -- name: Create eda project - infra.eda_configuration.project: - name: my_project - description: my awesome project - url: https://github.com/ansible/ansible-rulebook.git - credential: test_token - state: present - eda_host: eda.example.com - eda_username: admin - eda_password: Sup3r53cr3t - -""" - -from ..module_utils.eda_module import EDAModule - - -def main(): - # Any additional arguments that are not fields of the item can be added here - argument_spec = dict( - name=dict(required=True), - new_name=dict(), - description=dict(), - url=dict(required=True, aliases=["scm_url"]), - tls_validation=dict(type="bool", default=True), - credential=dict(), - state=dict(choices=["present", "absent"], default="present"), - ) - - # Create a module for ourselves - module = EDAModule(argument_spec=argument_spec) - - # Extract our parameters - name = module.params.get("name") - new_name = module.params.get("new_name") - state = module.params.get("state") - - new_fields = {} - - # Attempt to look up an existing item based on the provided data - existing_item = module.get_one("projects", name_or_id=name, key="req_url") - - if state == "absent": - # If the state was absent we can let the module delete it if needed, the module will handle exiting from this - module.delete_if_needed(existing_item, key="req_url") - - # Create the data that gets sent for create and update - # Remove these two comments for final - # Check that Links and groups works with this. - new_fields["name"] = new_name if new_name else (module.get_item_name(existing_item) if existing_item else name) - for field_name in ( - "description", - "url", - "tls_validation", - ): - field_val = module.params.get(field_name) - if field_val is not None: - new_fields[field_name] = field_val - - if module.params.get("credential") is not None: - new_fields["credential_id"] = module.resolve_name_to_id("credentials", module.params.get("credential")) - - # If the state was present and we can let the module build or update the existing item, this will return on its own - module.create_or_update_if_needed( - existing_item, - new_fields, - endpoint="projects", - item_type="projects", - key="req_url", - ) - - -if __name__ == "__main__": - main() diff --git a/plugins/modules/project_sync.py b/plugins/modules/project_sync.py deleted file mode 100644 index 1c30a9e..0000000 --- a/plugins/modules/project_sync.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/python -# coding: utf-8 -*- - -# (c) 2023, Chris Renwick <@crenwick93> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["preview"], - "supported_by": "community", -} - - -DOCUMENTATION = """ ---- -module: project_sync -author: "Tom Page (@Tompage1994)" -short_description: Sync a project in EDA Controller -description: - - Sync projects in EDA Controller -options: - name: - description: - - The name of the project. - required: True - type: str - wait: - description: - - Wait for the project to finish syncing before returning. - required: false - default: True - type: bool - interval: - description: - - The interval to request an update from EDA Controller. - required: False - default: 1 - type: float - timeout: - description: - - If waiting for the project to update this will abort after this - amount of seconds - type: int - -extends_documentation_fragment: infra.eda_configuration.auth -""" - - -EXAMPLES = """ -- name: Create eda project - infra.eda_configuration.project_sync: - name: my_project - wait: true - interval: 5 - timeout: 60 - eda_host: eda.example.com - eda_username: admin - eda_password: Sup3r53cr3t - -""" - -from ..module_utils.eda_module import EDAModule - - -def main(): - # Any additional arguments that are not fields of the item can be added here - argument_spec = dict( - name=dict(required=True), - wait=dict(default=True, type="bool"), - interval=dict(default=1.0, type="float"), - timeout=dict(default=None, type="int"), - ) - - # Create a module for ourselves - module = EDAModule(argument_spec=argument_spec) - - # Extract our parameters - name = module.params.get("name") - wait = module.params.get("wait") - interval = module.params.get("interval") - timeout = module.params.get("timeout") - - # Attempt to look up an existing item based on the provided data - project = module.get_one("projects", name_or_id=name, key="req_url", allow_none=False) - - module.sync_project(project["id"], wait, interval, timeout) - - -if __name__ == "__main__": - main() diff --git a/plugins/modules/rulebook_activation.py b/plugins/modules/rulebook_activation.py deleted file mode 100644 index c198fec..0000000 --- a/plugins/modules/rulebook_activation.py +++ /dev/null @@ -1,233 +0,0 @@ -#!/usr/bin/python -# coding: utf-8 -*- - -# (c) 2023, Tom Page <@Tompage1994> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["preview"], - "supported_by": "community", -} - - -DOCUMENTATION = """ ---- -module: rulebook_activation -author: "Tom Page (@Tompage1994)" -short_description: Manage a rulebook_activation in EDA Controller -description: - - Create, enable, disable and delete rulebook activations in EDA Controller -options: - name: - description: - - The name of the rulebook activation. - required: True - type: str - description: - description: - - The description of the rulebook_activation. - required: False - type: str - project: - description: - - The project from which the rulebook is found. - required: False - type: str - rulebook: - description: - - The name of the rulebook to activate. - required: True - type: str - decision_environment: - description: - - The decision environment to be used. - required: True - type: str - restart_policy: - description: - - The policy used to determine whether to restart a rulebook. - required: False - choices: ["always", "never", "on-failure"] - default: "always" - type: str - extra_vars: - description: - - Specify C(extra_vars) for the template. - required: False - type: dict - awx_token: - description: - - The token used to authenticate to controller. - required: False - type: str - enabled: - description: - - Whether the rulebook activation is automatically enabled to run. - default: true - type: bool - state: - description: - - Desired state of the resource. - choices: ["present", "absent", "restarted"] - default: "present" - type: str - -extends_documentation_fragment: infra.eda_configuration.auth -""" - - -EXAMPLES = """ -- name: Create eda rulebook activation - infra.eda_configuration.rulebook_activation: - name: Github Hook - description: Hook to listen for changes in GitHub - project: eda_examples - rulebook: git-hook-deploy-rules.yml - decision_environment: my_de - extra_vars: - provider: github - repo_url: https://github.com/ansible/ansible-rulebook.git - enabled: true - awx_token: my_token - state: present - -- name: Restart eda rulebook activation - infra.eda_configuration.rulebook_activation: - name: Github Hook - state: restarted - -- name: Delete eda rulebook activation - infra.eda_configuration.rulebook_activation: - name: Github Hook - state: absent -""" - -from ..module_utils.eda_module import EDAModule -import json - - -def main(): - # Any additional arguments that are not fields of the item can be added here - argument_spec = dict( - name=dict(required=True), - description=dict(), - project=dict(), - rulebook=dict(required=True), - decision_environment=dict(required=True), - restart_policy=dict(choices=["always", "never", "on-failure"], default="always"), - extra_vars=dict(type="dict"), - enabled=dict(type="bool", default="true"), - state=dict(choices=["present", "absent", "restarted"], default="present"), - awx_token=dict(no_log=False), - ) - - # Create a module for ourselves - module = EDAModule(argument_spec=argument_spec, required_if=[("state", "present", ("rulebook", "decision_environment"))]) - - # Extract our parameters - name = module.params.get("name") - state = module.params.get("state") - - new_fields = {} - - # Attempt to look up an existing item based on the provided data - existing_item = module.get_one("activations", name_or_id=name, key="req_url") - - if state == "absent": - # If the state was absent we can let the module delete it if needed, the module will handle exiting from this - module.delete_if_needed(existing_item, key="req_url") - - if state == "restarted": - if module.params.get("enabled") is not None and not module.params.get("enabled"): - module.fail_json(msg="It is not possible to restart a disabled rulebook activation. Ensure it is set to enabled.") - # If the options want the activation enabled but it currently isn't then just run through as though enabling as that performs the restart - if existing_item["is_enabled"]: - # If the state was restarted we will hit the restart endpoint, the module will handle exiting from this - # If the item doesn't exist we will just create it anyway - module.trigger_post_action("activations/{id}/restart".format(id=existing_item["id"]), auto_exit=True) - - # Create the data that gets sent for create and update - # Remove these two comments for final - # Check that Links and groups works with this. - for field_name in ( - "name", - "description", - "restart_policy", - ): - field_val = module.params.get(field_name) - if field_val is not None: - new_fields[field_name] = field_val - - if module.params.get("enabled") is not None: - new_fields["is_enabled"] = module.params.get("enabled") - - if (module.params.get("project") is not None) and (module.params.get("rulebook") is not None): - new_fields["project_id"] = module.resolve_name_to_id("projects", module.params.get("project")) - new_fields["rulebook_id"] = module.resolve_name_to_id("rulebooks", - module.params.get("rulebook"), - data={"project_id": int(new_fields["project_id"])}, - ) - else: - new_fields["rulebook_id"] = module.resolve_name_to_id("rulebooks", module.params.get("rulebook")) - - if module.params.get("decision_environment") is not None: - new_fields["decision_environment_id"] = module.resolve_name_to_id("decision-environments", module.params.get("decision_environment")) - - if module.params.get("awx_token") is not None: - new_fields["awx_token_id"] = module.resolve_name_to_id("users/me/awx-tokens", module.params.get("awx_token")) - - # Create the extra_vars - if module.params.get("extra_vars") is not None: - if existing_item is not None: - new_fields["extra_var_id"] = -1 # Default it as something that isn't acceptable. Prove otherwise - if existing_item["extra_var_id"]: - # Check if matching existing extra_vars - existing_vars = module.get_by_id("extra-vars", id=existing_item["extra_var_id"]) - # Test if the same - if json.dumps(module.params.get("extra_vars")) == existing_vars["extra_var"]: - new_fields["extra_var_id"] = existing_item["extra_var_id"] - else: - new_fields["extra_var_id"] = module.create_no_name( - {"extra_var": json.dumps(module.params.get("extra_vars"))}, - endpoint="extra-vars", - item_type="extra_vars" - )["id"] - - if existing_item is not None: - # If the activation already exists, all we can do is change whether it is enabled or disabled. - # The module will exit from this section - - # First, fail; if trying to change anything other than being enabled - if ("description" in new_fields and existing_item["description"] != new_fields["description"] - or "restart_policy" in new_fields and existing_item["restart_policy"] != new_fields["restart_policy"] - or "project_id" in new_fields and existing_item["project_id"] != new_fields["project_id"] - or "rulebook_id" in new_fields and existing_item["rulebook_id"] != new_fields["rulebook_id"] - or "decision_environment_id" in new_fields and existing_item["decision_environment_id"] != new_fields["decision_environment_id"] - or "awx_token_id" in new_fields and existing_item["awx_token_id"] != new_fields["awx_token_id"] - or "extra_var_id" in new_fields and existing_item["extra_var_id"] != new_fields["extra_var_id"]): - module.fail_json(msg="Once an activation has been created it can only be enabled, disabled or deleted. Other changes cannot be made.") - - if module.params.get("enabled") is not None: - if module.params.get("enabled") and not existing_item["is_enabled"]: - module.trigger_post_action("activations/{id}/enable".format(id=existing_item["id"]), auto_exit=True) - elif (not module.params.get("enabled")) and existing_item["is_enabled"]: - module.trigger_post_action("activations/{id}/disable".format(id=existing_item["id"]), auto_exit=True) - module.exit_json(**module.json_output) - - # If the state was present and we can let the module build or update the existing item, this will return on its own - module.create_if_needed( - existing_item, - new_fields, - endpoint="activations", - item_type="rulebook_activations", - ) - - -if __name__ == "__main__": - main() diff --git a/plugins/modules/user.py b/plugins/modules/user.py deleted file mode 100644 index 1e056b4..0000000 --- a/plugins/modules/user.py +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/python -# coding: utf-8 -*- - -# (c) 2023, Tom Page <@Tompage1994> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["preview"], - "supported_by": "community", -} - - -DOCUMENTATION = """ ---- -module: user -author: "Tom Page (@Tompage1994)" -short_description: Manage a user in EDA Controller -description: - - Create, update and delete users in EDA Controller -options: - username: - description: - - Name of the user to create, remove, or modify. - required: true - type: str - new_username: - description: - - Setting this option will change the existing username (looked up via the name field). - type: str - first_name: - description: - - User's first name. - type: str - last_name: - description: - - User's last name. - type: str - email: - description: - - User's email address. That address must be correctly formed. - type: str - password: - description: - - User's password as a clear string. - type: str - update_secrets: - description: - - C(true) will always change password if user specifies password. - - C(false) will only set the password if other values change too. - type: bool - default: true - roles: - description: - - The roles the user is provided with. - - Current values are C(Viewer), C(Auditor), C(Editor), C(Contributor), C(Operator), C(Admin) - type: list - elements: str - state: - description: - - Desired state of the resource. - choices: ["present", "absent"] - default: "present" - type: str - -extends_documentation_fragment: infra.eda_configuration.auth -""" - - -EXAMPLES = """ -- name: Create eda user - infra.eda_configuration.user: - username: john_smith - first_name: john - last_name: smith - email: jsmith@example.com - password: my_p455word - roles: - - Viewer - - Auditor - - Contributor - state: present - eda_host: eda.example.com - eda_username: admin - eda_password: Sup3r53cr3t - -""" - -from ..module_utils.eda_module import EDAModule - - -def main(): - # Any additional arguments that are not fields of the item can be added here - argument_spec = dict( - username=dict(required=True), - new_username=dict(), - first_name=dict(), - last_name=dict(), - email=dict(), - password=dict(no_log=True), - update_secrets=dict(type='bool', default=True, no_log=False), - roles=dict(type="list", elements="str"), - state=dict(choices=["present", "absent"], default="present"), - ) - - # Create a module for ourselves - module = EDAModule(argument_spec=argument_spec) - - # Extract our parameters - username = module.params.get("username") - new_username = module.params.get("new_username") - state = module.params.get("state") - - new_fields = {} - - # Attempt to look up an existing item based on the provided data - existing_item = module.get_one("users", name_or_id=username, key="req_url") - - if state == "absent": - # If the state was absent we can let the module delete it if needed, the module will handle exiting from this - module.delete_if_needed(existing_item, key="req_url") - - # Create the data that gets sent for create and update - # Remove these two comments for final - # Check that Links and groups works with this. - new_fields["username"] = new_username if new_username else (existing_item["username"] if existing_item else username) - for field_name in ( - "first_name", - "last_name", - "email", - "password", - ): - field_val = module.params.get(field_name) - if field_val is not None: - new_fields[field_name] = field_val - - if module.params.get("roles") is not None: - roles = module.params.get("roles") - new_fields["roles"] = list(map(lambda role: module.resolve_name_to_id("roles", role), roles)) - - # If the state was present and we can let the module build or update the existing item, this will return on its own - module.create_or_update_if_needed( - existing_item, - new_fields, - endpoint="users", - item_type="users", - key="req_url", - ) - - -if __name__ == "__main__": - main() diff --git a/plugins/modules/user_token.py b/plugins/modules/user_token.py deleted file mode 100644 index da4f01d..0000000 --- a/plugins/modules/user_token.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/python -# coding: utf-8 -*- - -# (c) 2024, Derek Waters <@derekwaters> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["preview"], - "supported_by": "community", -} - - -DOCUMENTATION = """ ---- -module: user_token -author: "Derek Waters (@derekwaters)" -short_description: Manage the user tokens of the current user in EDA Controller -description: - - Create, update and delete user tokens in EDA Controller -options: - name: - description: - - The name of the token. - required: True - type: str - new_name: - description: - - Setting this option will change the existing name (looked up via the name field). - type: str - description: - description: - - The description of the token. - required: False - type: str - token: - description: - - The token data to set for the user. - required: True - type: str - -extends_documentation_fragment: infra.eda_configuration.auth -""" - - -EXAMPLES = """ -- name: Create eda user token - infra.eda_configuration.user_token: - name: my_user_token - description: my user token for accessing AAP - token: SOMETOKENDATA - eda_host: eda.example.com - eda_username: admin - eda_password: Sup3r53cr3t - -""" - -from ..module_utils.eda_module import EDAModule - - -def main(): - # Any additional arguments that are not fields of the item can be added here - argument_spec = dict( - name=dict(required=True), - new_name=dict(), - description=dict(), - token=dict(required=True, no_log=True), - ) - - # Create a module for ourselves - module = EDAModule(argument_spec=argument_spec) - - # Extract our parameters - name = module.params.get("name") - new_name = module.params.get("new_name") - - new_fields = {} - - # There is no way (that I can find) to search for an existing token - # based on name. This module can only attempt to create new tokens - # and fail safe if the token already exists (there is no way to patch - # an existing token) - - # Create the data that gets sent for create and update - # Remove these two comments for final - # Check that Links and groups works with this. - new_fields["name"] = new_name if new_name else name - for field_name in ( - "description", - "token", - ): - field_val = module.params.get(field_name) - if field_val is not None: - new_fields[field_name] = field_val - - module.create_if_needed( - None, - new_fields, - endpoint="users/me/awx-tokens", - item_type="awx-tokens", - treat_conflict_as_unchanged=True - ) - - -if __name__ == "__main__": - main() diff --git a/roles/credential/README.md b/roles/credential/README.md index 729a716..8805731 100644 --- a/roles/credential/README.md +++ b/roles/credential/README.md @@ -51,8 +51,8 @@ This also speeds up the overall role. |`name`|""|yes|str|Credential name. Must be lower case containing only alphanumeric characters and underscores.| |`new_name`|""|no|str|Setting this option will change the existing name (looked up via the name field.)| |`description`|""|no|str|Description to use for the credential.| -|`username`|""|yes|str|The username of the credential.| -|`secret`|""|yes|str|The token or password for the given username (depending upon the credential type).| +|`organization`|""|no|Organization this Credential belongs to.| +|`inputs`|""|no|Credential inputs where the keys are var names used in templating. Refer to the EDA controller documentation for example syntax.| |`credential_type`|"GitHub Personal Access Token"|yes|str|The type of the credential.| |`state`|`present`|no|str|Desired state of the credential.| @@ -83,7 +83,7 @@ eda_credentials: vars: eda_validate_certs: false # Define following vars here, or in eda_configs/eda_auth.yml - # eda_host: ansible-eda-web-svc-test-credential.example.com + # controller_host: ansible-eda-web-svc-test-credential.example.com # eda_token: changeme pre_tasks: - name: Include vars from eda_configs directory @@ -93,7 +93,7 @@ eda_credentials: tags: - always roles: - - ../../credential + - infra.eda_configuration.credential ``` ## License diff --git a/roles/credential/meta/argument_specs.yml b/roles/credential/meta/argument_specs.yml index 0c8bf3f..521a8b0 100644 --- a/roles/credential/meta/argument_specs.yml +++ b/roles/credential/meta/argument_specs.yml @@ -45,7 +45,7 @@ argument_specs: description: This variable enables secure logging across all roles as a default. # Generic across all roles - eda_host: + controller_host: required: false description: URL to the EDA Controller Server. type: str @@ -59,11 +59,11 @@ argument_specs: required: false description: Specify the timeout Ansible should use in requests to the EDA Controller host. type: float - eda_username: + controller_username: required: false description: User for authentication on EDA Controller type: str - eda_password: + controller_password: required: false description: User's password For EDA Controller type: str diff --git a/roles/credential/tasks/main.yml b/roles/credential/tasks/main.yml index 6f73552..f885526 100644 --- a/roles/credential/tasks/main.yml +++ b/roles/credential/tasks/main.yml @@ -2,19 +2,19 @@ # Create EDA Controller Credential - name: Add EDA Controller credential - infra.eda_configuration.credential: - name: "{{ __credential_item.name }}" - new_name: "{{ __credential_item.new_name | default(omit) }}" - description: "{{ __credential_item.description | default(omit) }}" - credential_type: "{{ __credential_item.credential_type | default('GitHub Personal Access Token') }}" - username: "{{ __credential_item.username | default(omit) }}" - secret: "{{ __credential_item.secret | default(omit) }}" - state: "{{ __credential_item.state | default(eda_state | default('present')) }}" - eda_host: "{{ eda_host | default(eda_hostname) }}" - eda_username: "{{ eda_username | default(omit) }}" - eda_password: "{{ eda_password | default(omit) }}" - validate_certs: "{{ eda_validate_certs | default(omit) }}" - request_timeout: "{{ eda_request_timeout | default(omit) }}" + ansible.eda.credential: + name: "{{ __credential_item.name }}" + new_name: "{{ __credential_item.new_name | default(omit) }}" + description: "{{ __credential_item.description | default(omit) }}" + organization_name: "{{ __credential_item.organization | default(omit) }}" + credential_type_name: "{{ __credential_item.credential_type | default('GitHub Personal Access Token') }}" + inputs: "{{ __credential_item.inputs | default(omit) }}" + state: "{{ __credential_item.state | default(eda_state | default('present')) }}" + controller_host: "{{ eda_host | default(eda_hostname) }}" + controller_username: "{{ eda_username | default(omit) }}" + controller_password: "{{ eda_password | default(omit) }}" + validate_certs: "{{ eda_validate_certs | default(omit) }}" + request_timeout: "{{ eda_request_timeout | default(omit) }}" loop: "{{ eda_credentials }}" loop_control: loop_var: "__credential_item" diff --git a/roles/credential/tests/test.yml b/roles/credential/tests/test.yml index 460307a..2fd4e4d 100644 --- a/roles/credential/tests/test.yml +++ b/roles/credential/tests/test.yml @@ -6,7 +6,7 @@ vars: eda_validate_certs: false # Define following vars here, or in eda_configs/eda_auth.yml - # eda_host: ansible-eda-web-svc-test-project.example.com + # controller_host: ansible-eda-web-svc-test-project.example.com # eda_token: changeme pre_tasks: - name: Include vars from eda_configs directory diff --git a/roles/decision_environment/README.md b/roles/decision_environment/README.md index b4b678f..e2954df 100644 --- a/roles/decision_environment/README.md +++ b/roles/decision_environment/README.md @@ -53,6 +53,7 @@ This also speeds up the overall role. |`description`|""|no|str|Description to use for the Project.| |`image_url`|""|yes|str|A URL to a a container image to use for the decision environment.| |`credential`|""|no|str|The credential used to access the container registry holding the image.| +|`organization`|""|no|Organization this decision environment belongs to.| |`state`|`present`|no|str|Desired state of the decision environment.| ### Standard Decision Environment Data Structure @@ -81,7 +82,7 @@ eda_decision_environments: vars: eda_validate_certs: false # Define following vars here, or in eda_configs/eda_auth.yml - # eda_host: ansible-eda-web-svc-test-project.example.com + # controller_host: ansible-eda-web-svc-test-project.example.com # eda_token: changeme pre_tasks: - name: Include vars from eda_configs directory @@ -91,7 +92,7 @@ eda_decision_environments: tags: - always roles: - - ../../decision_environment + - infra.eda_configuration.decision_environment ``` ## License diff --git a/roles/decision_environment/meta/argument_specs.yml b/roles/decision_environment/meta/argument_specs.yml index 204812f..bd3c910 100644 --- a/roles/decision_environment/meta/argument_specs.yml +++ b/roles/decision_environment/meta/argument_specs.yml @@ -45,7 +45,7 @@ argument_specs: description: This variable enables secure logging across all roles as a default. # Generic across all roles - eda_host: + controller_host: required: false description: URL to the EDA Controller Server. type: str @@ -59,11 +59,11 @@ argument_specs: required: false description: Specify the timeout Ansible should use in requests to the EDA Controller host. type: float - eda_username: + controller_username: required: false description: User for authentication on EDA Controller type: str - eda_password: + controller_password: required: false description: User's password For EDA Controller type: str diff --git a/roles/decision_environment/tasks/main.yml b/roles/decision_environment/tasks/main.yml index 55c62b0..7483933 100644 --- a/roles/decision_environment/tasks/main.yml +++ b/roles/decision_environment/tasks/main.yml @@ -2,18 +2,19 @@ # Create EDA Controller Decision Environment - name: Add EDA Controller decision environment - infra.eda_configuration.decision_environment: - name: "{{ __de_item.name }}" - new_name: "{{ __de_item.new_name | default(omit) }}" - description: "{{ __de_item.description | default(omit) }}" - image_url: "{{ __de_item.image_url | default(omit) }}" - credential: "{{ __de_item.credential | default(omit) }}" - state: "{{ __de_item.state | default(eda_state | default('present')) }}" - eda_host: "{{ eda_host | default(eda_hostname) }}" - eda_username: "{{ eda_username | default(omit) }}" - eda_password: "{{ eda_password | default(omit) }}" - validate_certs: "{{ eda_validate_certs | default(omit) }}" - request_timeout: "{{ eda_request_timeout | default(omit) }}" + ansible.eda.decision_environment: + name: "{{ __de_item.name }}" + new_name: "{{ __de_item.new_name | default(omit) }}" + description: "{{ __de_item.description | default(omit) }}" + image_url: "{{ __de_item.image_url | default(omit) }}" + credential: "{{ __de_item.credential | default(omit) }}" + organization_name: "{{ __de_item.organization | default(omit) }}" + state: "{{ __de_item.state | default(eda_state | default('present')) }}" + controller_host: "{{ eda_host | default(eda_hostname) }}" + controller_username: "{{ eda_username | default(omit) }}" + controller_password: "{{ eda_password | default(omit) }}" + validate_certs: "{{ eda_validate_certs | default(omit) }}" + request_timeout: "{{ eda_request_timeout | default(omit) }}" loop: "{{ eda_decision_environments }}" loop_control: loop_var: "__de_item" diff --git a/roles/decision_environment/tests/test.yml b/roles/decision_environment/tests/test.yml index 270e94a..549a7bd 100644 --- a/roles/decision_environment/tests/test.yml +++ b/roles/decision_environment/tests/test.yml @@ -6,7 +6,7 @@ vars: eda_validate_certs: false # Define following vars here, or in eda_configs/eda_auth.yml - # eda_host: ansible-eda-web-svc-test-project.example.com + # controller_host: ansible-eda-web-svc-test-project.example.com # eda_token: changeme pre_tasks: - name: Include vars from eda_configs directory diff --git a/roles/dispatch/meta/argument_specs.yml b/roles/dispatch/meta/argument_specs.yml index 8dd5c4d..70e7532 100644 --- a/roles/dispatch/meta/argument_specs.yml +++ b/roles/dispatch/meta/argument_specs.yml @@ -64,12 +64,12 @@ argument_specs: required: false description: Whether or not to validate the Ansible EDA Server's SSL certificate. type: str - eda_username: + controller_username: default: None required: false description: Admin User on the Ansible EDA Server. Either username / password or oauthtoken need to be specified. type: str - eda_password: + controller_password: default: None required: false description: eda Admin User's password on the Ansible EDA Server. This should be stored in an Ansible Vault at vars/eda-secrets.yml or elsewhere and called from a parent playbook. diff --git a/roles/dispatch/tests/test.yml b/roles/dispatch/tests/test.yml index 5f85267..f7aab8b 100644 --- a/roles/dispatch/tests/test.yml +++ b/roles/dispatch/tests/test.yml @@ -6,8 +6,8 @@ vars: eda_validate_certs: false eda_hostname: eda.example.com - eda_username: admin - eda_password: changeme + controller_username: admin + controller_password: changeme collections: - awx.awx diff --git a/roles/project/README.md b/roles/project/README.md index fdc3b46..142df1c 100644 --- a/roles/project/README.md +++ b/roles/project/README.md @@ -52,7 +52,7 @@ This also speeds up the overall role. |`new_name`|""|no|str|Setting this option will change the existing name (looked up via the name field.)| |`description`|""|no|str|Description to use for the Project.| |`url`|""|yes|str|A URL to a remote archive, such as a Github Release or a build artifact stored in Artifactory and unpacks it into the project path for use. (Alias: scm_url)| -|`tls_validation`|true|no|bool|Whether the URL should validate using TLS.| +|`organization`|""|no|Organization this project belongs to.| |`credential`|""|no|str|The token needed to utilize the SCM URL.| |`state`|`present`|no|str|Desired state of the project.| @@ -83,7 +83,7 @@ eda_projects: vars: eda_validate_certs: false # Define following vars here, or in eda_configs/eda_auth.yml - # eda_host: ansible-eda-web-svc-test-project.example.com + # controller_host: ansible-eda-web-svc-test-project.example.com # eda_token: changeme pre_tasks: - name: Include vars from eda_configs directory @@ -93,7 +93,7 @@ eda_projects: tags: - always roles: - - ../../project + - infra.eda_configuration.project ``` ## License diff --git a/roles/project/meta/argument_specs.yml b/roles/project/meta/argument_specs.yml index 42dc125..c487281 100644 --- a/roles/project/meta/argument_specs.yml +++ b/roles/project/meta/argument_specs.yml @@ -45,7 +45,7 @@ argument_specs: description: This variable enables secure logging across all roles as a default. # Generic across all roles - eda_host: + controller_host: required: false description: URL to the EDA Controller Server. type: str @@ -59,11 +59,11 @@ argument_specs: required: false description: Specify the timeout Ansible should use in requests to the EDA Controller host. type: float - eda_username: + controller_username: required: false description: User for authentication on EDA Controller type: str - eda_password: + controller_password: required: false description: User's password For EDA Controller type: str diff --git a/roles/project/tasks/main.yml b/roles/project/tasks/main.yml index 4d12a99..ca03b0c 100644 --- a/roles/project/tasks/main.yml +++ b/roles/project/tasks/main.yml @@ -2,19 +2,20 @@ # Create EDA Controller Project - name: Add EDA Controller project - infra.eda_configuration.project: - name: "{{ __project_item.name }}" - new_name: "{{ __project_item.new_name | default(omit) }}" - description: "{{ __project_item.description | default(omit) }}" - url: "{{ __project_item.url | default(__project_item.scm_url | default(omit)) }}" - tls_validation: "{{ __project_item.tls_validation | default(omit) }}" - credential: "{{ __project_item.credential | default(omit) }}" - state: "{{ __project_item.state | default(eda_state | default('present')) }}" - eda_host: "{{ eda_host | default(eda_hostname) }}" - eda_username: "{{ eda_username | default(omit) }}" - eda_password: "{{ eda_password | default(omit) }}" - validate_certs: "{{ eda_validate_certs | default(omit) }}" - request_timeout: "{{ eda_request_timeout | default(omit) }}" + ansible.eda.project: + name: "{{ __project_item.name }}" + new_name: "{{ __project_item.new_name | default(omit) }}" + description: "{{ __project_item.description | default(omit) }}" + url: "{{ __project_item.url | default(__project_item.scm_url | default(omit)) }}" + # tls_validation: "{{ __project_item.tls_validation | default(omit) }}" + credential: "{{ __project_item.credential | default(omit) }}" + organization_name: "{{ __project_item.organization | default(omit) }}" + state: "{{ __project_item.state | default(eda_state | default('present')) }}" + controller_host: "{{ eda_host | default(eda_hostname) }}" + controller_username: "{{ eda_username | default(omit) }}" + controller_password: "{{ eda_password | default(omit) }}" + validate_certs: "{{ eda_validate_certs | default(omit) }}" + request_timeout: "{{ eda_request_timeout | default(omit) }}" loop: "{{ eda_projects }}" loop_control: loop_var: "__project_item" diff --git a/roles/project/tests/test.yml b/roles/project/tests/test.yml index 4cc5b5e..c5b814e 100644 --- a/roles/project/tests/test.yml +++ b/roles/project/tests/test.yml @@ -6,7 +6,7 @@ vars: eda_validate_certs: false # Define following vars here, or in eda_configs/eda_auth.yml - # eda_host: ansible-eda-web-svc-test-project.example.com + # controller_host: ansible-eda-web-svc-test-project.example.com # eda_token: changeme pre_tasks: - name: Include vars from eda_configs directory diff --git a/roles/project_sync/README.md b/roles/project_sync/README.md deleted file mode 100644 index d9e96ef..0000000 --- a/roles/project_sync/README.md +++ /dev/null @@ -1,105 +0,0 @@ -# infra.eda_configuration.project - -## Description - -An Ansible Role to create Projects in EDA Controller. - -## Variables - -|Variable Name|Default Value|Required|Description|Example| -|:---:|:---:|:---:|:---:|:---:| -|`eda_host`|""|yes|URL to the EDA Controller (alias: `eda_hostname`)|127.0.0.1| -|`eda_username`|""|yes|Admin User on the EDA Controller || -|`eda_password`|""|yes|EDA Controller Admin User's password on the EDA Controller Server. This should be stored in an Ansible Vault at vars/tower-secrets.yml or elsewhere and called from a parent playbook.|| -|`eda_validate_certs`|`False`|no|Whether or not to validate the Ansible EDA Controller Server's SSL certificate.|| -|`eda_request_timeout`|`10`|no|Specify the timeout Ansible should use in requests to the EDA Controller host.|| -|`eda_configuration_async_dir`|`null`|no|Sets the directory to write the results file for async tasks. The default value is set to `null` which uses the Ansible Default of `/root/.ansible_async/`.|| -|`eda_projects`|`see below`|yes|Data structure describing your projects, described below. Note that this role will only do anything if the `sync` suboption of this variable is set to true.|| - -### Secure Logging Variables - -The following Variables compliment each other. -If Both variables are not set, secure logging defaults to false. -The role defaults to False as normally the add project task does not include sensitive information. -eda_configuration_project_secure_logging defaults to the value of eda_configuration_secure_logging if it is not explicitly called. This allows for secure logging to be toggled for the entire suite of EDA Controller configuration roles with a single variable, or for the user to selectively use it. - -|Variable Name|Default Value|Required|Description| -|:---:|:---:|:---:|:---:| -|`eda_configuration_project_secure_logging`|`False`|no|Whether or not to include the sensitive Project role tasks in the log. Set this value to `True` if you will be providing your sensitive values from elsewhere.| -|`eda_configuration_secure_logging`|`False`|no|This variable enables secure logging as well, but is shared across multiple roles, see above.| - -### Asynchronous Retry Variables - -The following Variables set asynchronous retries for the role. -If neither of the retries or delay or retries are set, they will default to their respective defaults. -This allows for all items to be created, then checked that the task finishes successfully. -This also speeds up the overall role. - -|Variable Name|Default Value|Required|Description| -|:---:|:---:|:---:|:---:| -|`eda_configuration_async_retries`|50|no|This variable sets the number of retries to attempt for the role globally.| -|`eda_configuration_project_sync_async_retries`|`eda_configuration_async_retries`|no|This variable sets the number of retries to attempt for the role.| -|`eda_configuration_async_delay`|1|no|This sets the delay between retries for the role globally.| -|`eda_configuration_project_sync_async_delay`|`eda_configuration_async_delay`|no|This sets the delay between retries for the role.| - -## Data Structure - -### Project Variables - -|Variable Name|Default Value|Required|Type|Description| -|:---:|:---:|:---:|:---:|:---:| -|`name`|""|yes|str|Project name. Must be lower case containing only alphanumeric characters and underscores.| -|`sync`|false|no|bool|Whether to sync the project. By default it will not sync unless this is set to true.| -|`wait`|true|no|str|Whether to wait for the sync to complete| -|`interval`|`eda_configuration_project_sync_async_delay`|no|str|The interval which the sync task will be checked for completion| -|`timeout`|""|no|str|How long to wait for the sync task to complete| - -### Standard Project Data Structure - -#### Yaml Example - -```yaml ---- -eda_projects: - - name: my_project - description: my awesome project - url: https://github.com/ansible/ansible-rulebook.git - credential: test_token - wait: true - interval: 10 - sync: true -``` - -## Playbook Examples - -### Standard Role Usage - -```yaml ---- -- name: Sync project to EDA Controller - hosts: localhost - connection: local - gather_facts: false - vars: - eda_validate_certs: false - # Define following vars here, or in eda_configs/eda_auth.yml - # eda_host: ansible-eda-web-svc-test-project.example.com - # eda_token: changeme - pre_tasks: - - name: Include vars from eda_configs directory - ansible.builtin.include_vars: - dir: ./vars - extensions: ["yml"] - tags: - - always - roles: - - ../../project_sync -``` - -## License - -[GPLv3+](https://github.com/redhat-cop/eda_configuration#licensing) - -## Author - -[Tom Page](https://github.com/Tompage1994/) diff --git a/roles/project_sync/defaults/main.yml b/roles/project_sync/defaults/main.yml deleted file mode 100644 index c71af40..0000000 --- a/roles/project_sync/defaults/main.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -eda_projects: [] - -eda_configuration_project_secure_logging: "{{ eda_configuration_secure_logging | default(false) }}" -eda_configuration_project_sync_async_retries: "{{ eda_configuration_async_retries | default(50) }}" -eda_configuration_project_sync_async_delay: "{{ eda_configuration_async_delay | default(1) }}" -eda_configuration_async_dir: null -... diff --git a/roles/project_sync/meta/argument_specs.yml b/roles/project_sync/meta/argument_specs.yml deleted file mode 100644 index f769329..0000000 --- a/roles/project_sync/meta/argument_specs.yml +++ /dev/null @@ -1,70 +0,0 @@ ---- -argument_specs: - main: - short_description: An Ansible Role to sync projects in EDA controller. - options: - eda_projects: - default: [] - required: false - description: Data structure describing your projects to manage. If the sync option is set then the project will be synced - type: list - elements: dict - - # Async variables - eda_configuration_project_sync_async_retries: - default: "{{ eda_configuration_async_retries | default(50) }}" - required: false - description: This variable sets the number of retries to attempt for the role. - eda_configuration_async_retries: - default: 50 - required: false - description: This variable sets number of retries across all roles as a default. - eda_configuration_project_sync_async_delay: - default: "{{ eda_configuration_async_delay | default(1) }}" - required: false - description: This variable sets delay between retries for the role. - eda_configuration_async_delay: - default: 1 - required: false - description: This variable sets delay between retries across all roles as a default. - eda_configuration_async_dir: - default: null - required: false - description: Sets the directory to write the results file for async tasks. The default value is set to `null` which uses the Ansible Default of `/root/.ansible_async/`. - - # No_log variables - eda_configuration_project_secure_logging: - default: "{{ eda_configuration_secure_logging | default(false) }}" - required: false - type: bool - description: Whether or not to include the sensitive role tasks in the log. Set this value to `true` if you will be providing your sensitive values from elsewhere. - eda_configuration_secure_logging: - default: false - required: false - type: bool - description: This variable enables secure logging across all roles as a default. - - # Generic across all roles - eda_host: - required: false - description: URL to the EDA Controller Server. - type: str - eda_validate_certs: - default: true - required: false - description: Whether or not to validate the EDA Controller Server's SSL certificate. - type: str - eda_request_timeout: - default: 10 - required: false - description: Specify the timeout Ansible should use in requests to the EDA Controller host. - type: float - eda_username: - required: false - description: User for authentication on EDA Controller - type: str - eda_password: - required: false - description: User's password For EDA Controller - type: str -... diff --git a/roles/project_sync/meta/main.yml b/roles/project_sync/meta/main.yml deleted file mode 100644 index 697a7df..0000000 --- a/roles/project_sync/meta/main.yml +++ /dev/null @@ -1,43 +0,0 @@ ---- -galaxy_info: - role_name: "project_sync" - author: "Tom Page" - description: "An Ansible Role to create a project in EDA Controller." - company: "Red Hat" - - # If the issue tracker for your role is not on github, uncomment the - # next line and provide a value - # issue_tracker_url: http://example.com/issue/tracker - license: "GPLv3+" - - min_ansible_version: 2.15.0 - - # 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: - - # - # platforms is a list of platforms, and each platform has a name and a list of versions. - # - platforms: - - name: "EL" - versions: - - "all" - - galaxy_tags: - - "edacontroller" - - "eda" - - "configuration" - - "project" - - "projects" - - "sync" - -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/roles/project_sync/tasks/main.yml b/roles/project_sync/tasks/main.yml deleted file mode 100644 index 0f89887..0000000 --- a/roles/project_sync/tasks/main.yml +++ /dev/null @@ -1,41 +0,0 @@ ---- - -# Sync EDA Controller Project -- name: Sync EDA Controller project - infra.eda_configuration.project_sync: - name: "{{ __project_sync_item.name }}" - wait: "{{ __project_sync_item.wait | default(omit) }}" - interval: "{{ __project_sync_item.interval | default(eda_configuration_project_sync_async_delay) }}" - timeout: "{{ __project_sync_item.timeout | default(omit) }}" - eda_host: "{{ eda_host | default(eda_hostname) }}" - eda_username: "{{ eda_username | default(omit) }}" - eda_password: "{{ eda_password | default(omit) }}" - validate_certs: "{{ eda_validate_certs | default(omit) }}" - request_timeout: "{{ eda_request_timeout | default(omit) }}" - loop: "{{ eda_projects }}" - loop_control: - loop_var: "__project_sync_item" - when: __project_sync_item.sync | default(false) - no_log: "{{ eda_configuration_project_secure_logging }}" - async: 1000 - poll: 0 - register: __projects_sync_job_async - changed_when: not __projects_sync_job_async.changed - vars: - ansible_async_dir: '{{ eda_configuration_async_dir }}' - -- name: "Sync project | Wait for finish syncing the project" - ansible.builtin.async_status: - jid: "{{ __projects_sync_job_async_result_item.ansible_job_id }}" - register: __projects_sync_job_async_result - until: __projects_sync_job_async_result.finished - retries: "{{ eda_configuration_project_sync_async_retries }}" - delay: "{{ eda_configuration_project_sync_async_delay }}" - loop: "{{ __projects_sync_job_async.results }}" - loop_control: - loop_var: __projects_sync_job_async_result_item - when: __projects_sync_job_async_result_item.ansible_job_id is defined - no_log: "{{ eda_configuration_project_secure_logging }}" - vars: - ansible_async_dir: '{{ eda_configuration_async_dir }}' -... diff --git a/roles/project_sync/tests/test.yml b/roles/project_sync/tests/test.yml deleted file mode 100644 index 53f01c2..0000000 --- a/roles/project_sync/tests/test.yml +++ /dev/null @@ -1,20 +0,0 @@ ---- -- name: Sync project on EDA Controller - hosts: localhost - connection: local - gather_facts: false - vars: - eda_validate_certs: false - # Define following vars here, or in eda_configs/eda_auth.yml - # eda_host: ansible-eda-web-svc-test-project.example.com - # eda_token: changeme - pre_tasks: - - name: Include vars from eda_configs directory - ansible.builtin.include_vars: - dir: ./vars - extensions: ["yml"] - tags: - - always - roles: - - ../../project_sync -... diff --git a/roles/project_sync/tests/vars/projects.yml b/roles/project_sync/tests/vars/projects.yml deleted file mode 100644 index d5b5c7e..0000000 --- a/roles/project_sync/tests/vars/projects.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -eda_projects: - - name: my_project - description: my awesome project - url: https://github.com/ansible/ansible-rulebook.git - credential: test_token - sync: true - interval: 5 - timeout: 30 - wait: true -... diff --git a/roles/rulebook_activation/README.md b/roles/rulebook_activation/README.md index dbed80c..aa8792a 100644 --- a/roles/rulebook_activation/README.md +++ b/roles/rulebook_activation/README.md @@ -58,6 +58,12 @@ This also speeds up the overall role. |`awx_token`|""|no|str|The token used to authenticate to controller.| |`enabled`|"true"|no|str|Whether the rulebook activation is automatically enabled to run.| |`state`|`present`|no|str|Desired state of the rulebook activation.| +|`organization_name`|""|no|str|The name of the organization.| +|`eda_credentials`|""|no|list|A list of IDs for EDA credentials used by the rulebook activation.| +|`k8s_service_name`|""|no|str|The name of the Kubernetes service associated with this rulebook activation.| +|`swap_single_source`|"true"|no|bool|Allow swapping of single sources in a rulebook without name match.| +|`event_streams`|""|no|list|A list of event stream names that this rulebook activation listens to.| +|`log_level`|""|no|str|Allow setting the desired log level.| ### Standard rulebook activation Data Structure @@ -91,7 +97,7 @@ eda_rulebook_activations: vars: eda_validate_certs: false # Define following vars here, or in eda_configs/eda_auth.yml - # eda_host: ansible-eda-web-svc-test-project.example.com + # controller_host: ansible-eda-web-svc-test-project.example.com # eda_token: changeme pre_tasks: - name: Include vars from eda_configs directory diff --git a/roles/rulebook_activation/meta/argument_specs.yml b/roles/rulebook_activation/meta/argument_specs.yml index 23dbcf1..19ed5d3 100644 --- a/roles/rulebook_activation/meta/argument_specs.yml +++ b/roles/rulebook_activation/meta/argument_specs.yml @@ -45,7 +45,7 @@ argument_specs: description: This variable enables secure logging across all roles as a default. # Generic across all roles - eda_host: + controller_host: required: false description: URL to the EDA Controller Server. type: str @@ -59,11 +59,11 @@ argument_specs: required: false description: Specify the timeout Ansible should use in requests to the EDA Controller host. type: float - eda_username: + controller_username: required: false description: User for authentication on EDA Controller type: str - eda_password: + controller_password: required: false description: User's password For EDA Controller type: str diff --git a/roles/rulebook_activation/tasks/main.yml b/roles/rulebook_activation/tasks/main.yml index 1009d3d..f92ea53 100644 --- a/roles/rulebook_activation/tasks/main.yml +++ b/roles/rulebook_activation/tasks/main.yml @@ -2,7 +2,7 @@ # Create EDA Controller Rulebook Activation - name: Add EDA Controller rulebook activation - infra.eda_configuration.rulebook_activation: + ansible.eda.rulebook_activation: name: "{{ __ra_item.name }}" description: "{{ __ra_item.description | default(omit) }}" project: "{{ __ra_item.project | default(omit) }}" @@ -12,10 +12,16 @@ restart_policy: "{{ __ra_item.restart_policy | default(omit) }}" extra_vars: "{{ __ra_item.extra_vars | default(omit) }}" enabled: "{{ __ra_item.enabled | default(omit) }}" + organization_name: "{{ __ra_item.organization | default(omit) }}" + eda_credentials: "{{ __ra_item.eda_credentials | default(omit) }}" + k8s_service_name: "{{ __ra_item.k8s_service_name | default(omit) }}" + swap_single_source: "{{ __ra_item.swap_single_source | default(omit) }}" + event_streams: "{{ __ra_item.event_streams | default(omit) }}" + log_level: "{{ __ra_item.log_level | default(omit) }}" state: "{{ __ra_item.state | default(eda_state | default('present')) }}" - eda_host: "{{ eda_host | default(eda_hostname) }}" - eda_username: "{{ eda_username | default(omit) }}" - eda_password: "{{ eda_password | default(omit) }}" + controller_host: "{{ eda_host | default(eda_hostname) }}" + controller_username: "{{ eda_username | default(omit) }}" + controller_password: "{{ eda_password | default(omit) }}" validate_certs: "{{ eda_validate_certs | default(omit) }}" request_timeout: "{{ eda_request_timeout | default(omit) }}" loop: "{{ eda_rulebook_activations }}" diff --git a/roles/rulebook_activation/tests/test.yml b/roles/rulebook_activation/tests/test.yml index 51e91a7..4ad1576 100644 --- a/roles/rulebook_activation/tests/test.yml +++ b/roles/rulebook_activation/tests/test.yml @@ -6,7 +6,7 @@ vars: eda_validate_certs: false # Define following vars here, or in eda_configs/eda_auth.yml - # eda_host: ansible-eda-web-svc-test-project.example.com + # controller_host: ansible-eda-web-svc-test-project.example.com # eda_token: changeme pre_tasks: - name: Include vars from eda_configs directory diff --git a/roles/user/README.md b/roles/user/README.md index 92bd793..6e64eb4 100644 --- a/roles/user/README.md +++ b/roles/user/README.md @@ -1,4 +1,4 @@ -# infra.eda_configuration.user +# ansible.eda.user ## Description @@ -55,6 +55,7 @@ This also speeds up the overall role. |`email`|""|no|str|User's email address.| |`password`|""|yes|str|Password to use for the user.| |`update_secrets`|true|no|bool|Setting true will always change password if user specifies password. Password will only change if false if other fields change.| +|`is_superuser`|""|no|bool|Make user as superuser.| |`roles`|""|yes|list|Roles the user will have. Current acceptable values are: Viewer, Auditor, Editor, Contributor, Operator, Admin.| |`state`|`present`|no|str|Desired state of the user.| @@ -89,7 +90,7 @@ eda_users: vars: eda_validate_certs: false # Define following vars here, or in eda_configs/eda_auth.yml - # eda_host: ansible-eda-web-svc-test-user.example.com + # controller_host: ansible-eda-web-svc-test-user.example.com # eda_token: changeme pre_tasks: - name: Include vars from eda_configs directory diff --git a/roles/user/meta/argument_specs.yml b/roles/user/meta/argument_specs.yml index e2800f1..761e50f 100644 --- a/roles/user/meta/argument_specs.yml +++ b/roles/user/meta/argument_specs.yml @@ -45,7 +45,7 @@ argument_specs: description: This variable enables secure logging across all roles as a default. # Generic across all roles - eda_host: + controller_host: required: false description: URL to the EDA Controller Server. type: str @@ -59,11 +59,11 @@ argument_specs: required: false description: Specify the timeout Ansible should use in requests to the EDA Controller host. type: float - eda_username: + controller_username: required: false description: User for authentication on EDA Controller type: str - eda_password: + controller_password: required: false description: User's password For EDA Controller type: str diff --git a/roles/user/tasks/main.yml b/roles/user/tasks/main.yml index 4c7dcf7..23e540b 100644 --- a/roles/user/tasks/main.yml +++ b/roles/user/tasks/main.yml @@ -2,21 +2,22 @@ # Create EDA Controller user - name: Add EDA Controller user - infra.eda_configuration.user: - username: "{{ __user_item.username }}" - new_username: "{{ __user_item.new_username | default(omit) }}" - first_name: "{{ __user_item.first_name | default(omit) }}" - last_name: "{{ __user_item.last_name | default(omit) }}" - email: "{{ __user_item.email | default(omit) }}" - password: "{{ __user_item.password | default(omit) }}" - update_secrets: "{{ __user_item.update_secrets | default(omit) }}" - roles: "{{ __user_item.roles | default(omit) }}" - state: "{{ __user_item.state | default(eda_state | default('present')) }}" - eda_host: "{{ eda_host | default(eda_hostname) }}" - eda_username: "{{ eda_username | default(omit) }}" - eda_password: "{{ eda_password | default(omit) }}" - validate_certs: "{{ eda_validate_certs | default(omit) }}" - request_timeout: "{{ eda_request_timeout | default(omit) }}" + ansible.eda.user: + username: "{{ __user_item.username }}" + new_username: "{{ __user_item.new_username | default(omit) }}" + first_name: "{{ __user_item.first_name | default(omit) }}" + last_name: "{{ __user_item.last_name | default(omit) }}" + email: "{{ __user_item.email | default(omit) }}" + password: "{{ __user_item.password | default(omit) }}" + update_secrets: "{{ __user_item.update_secrets | default(omit) }}" + is_superuser: "{{ __user_item.is_superuser | default(omit) }}" + roles: "{{ __user_item.roles | default(omit) }}" + state: "{{ __user_item.state | default(eda_state | default('present')) }}" + controller_host: "{{ eda_host | default(eda_hostname) }}" + controller_username: "{{ eda_username | default(omit) }}" + controller_password: "{{ eda_password | default(omit) }}" + validate_certs: "{{ eda_validate_certs | default(omit) }}" + request_timeout: "{{ eda_request_timeout | default(omit) }}" loop: "{{ eda_users }}" loop_control: loop_var: "__user_item" diff --git a/roles/user/tests/test.yml b/roles/user/tests/test.yml index 243cffb..8a3cbdd 100644 --- a/roles/user/tests/test.yml +++ b/roles/user/tests/test.yml @@ -6,7 +6,7 @@ vars: eda_validate_certs: false # Define following vars here, or in eda_configs/eda_auth.yml - # eda_host: ansible-eda-web-svc-test-user.example.com + # controller_host: ansible-eda-web-svc-test-user.example.com # eda_token: changeme pre_tasks: - name: Include vars from eda_configs directory diff --git a/roles/user_token/README.md b/roles/user_token/README.md index 3b0b8ad..cc6609c 100644 --- a/roles/user_token/README.md +++ b/roles/user_token/README.md @@ -1,4 +1,4 @@ -# infra.eda_configuration.user_token +# ansible.eda.user_token ## Description @@ -79,7 +79,7 @@ eda_user_tokens: vars: eda_validate_certs: false # Define following vars here, or in eda_configs/eda_auth.yml - # eda_host: ansible-eda-web-svc-test-project.example.com + # controller_host: ansible-eda-web-svc-test-project.example.com # eda_token: changeme pre_tasks: - name: Include vars from eda_configs directory diff --git a/roles/user_token/meta/argument_specs.yml b/roles/user_token/meta/argument_specs.yml index 3bd855d..93f1320 100644 --- a/roles/user_token/meta/argument_specs.yml +++ b/roles/user_token/meta/argument_specs.yml @@ -45,7 +45,7 @@ argument_specs: description: This variable enables secure logging across all roles as a default. # Generic across all roles - eda_host: + controller_host: required: false description: URL to the EDA Controller Server. type: str @@ -59,11 +59,11 @@ argument_specs: required: false description: Specify the timeout Ansible should use in requests to the EDA Controller host. type: float - eda_username: + controller_username: required: false description: User for authentication on EDA Controller type: str - eda_password: + controller_password: required: false description: User's password For EDA Controller type: str diff --git a/roles/user_token/tasks/main.yml b/roles/user_token/tasks/main.yml index 0927e37..7404a7b 100644 --- a/roles/user_token/tasks/main.yml +++ b/roles/user_token/tasks/main.yml @@ -2,14 +2,14 @@ # Create EDA Controller User Tokens - name: Add EDA Controller user token - infra.eda_configuration.user_token: + ansible.eda.user_token: name: "{{ __token_item.name }}" new_name: "{{ __token_item.new_name | default(omit) }}" description: "{{ __token_item.description | default(omit) }}" token: "{{ __token_item.token | default(omit) }}" - eda_host: "{{ eda_host | default(eda_hostname) }}" - eda_username: "{{ eda_username | default(omit) }}" - eda_password: "{{ eda_password | default(omit) }}" + controller_host: "{{ eda_host | default(eda_hostname) }}" + controller_username: "{{ eda_username | default(omit) }}" + controller_password: "{{ eda_password | default(omit) }}" validate_certs: "{{ eda_validate_certs | default(omit) }}" request_timeout: "{{ eda_request_timeout | default(omit) }}" loop: "{{ eda_user_tokens }}" diff --git a/roles/user_token/tests/test.yml b/roles/user_token/tests/test.yml index c4adc44..a7f934a 100644 --- a/roles/user_token/tests/test.yml +++ b/roles/user_token/tests/test.yml @@ -6,7 +6,7 @@ vars: eda_validate_certs: false # Define following vars here, or in eda_configs/eda_auth.yml - # eda_host: ansible-eda-web-svc-test-project.example.com + # controller_host: ansible-eda-web-svc-test-project.example.com # eda_token: changeme pre_tasks: - name: Include vars from eda_configs directory diff --git a/tests/playbooks/eda_configs/eda_auth.yml b/tests/playbooks/eda_configs/eda_auth.yml index 34724ea..62d6f39 100644 --- a/tests/playbooks/eda_configs/eda_auth.yml +++ b/tests/playbooks/eda_configs/eda_auth.yml @@ -1,7 +1,7 @@ # User may add tower auth creds to this file and encrypt it using `ansible-vault` --- eda_hostname: http://localhost:8000 -eda_username: admin -eda_password: testpass +controller_username: admin +controller_password: testpass eda_validate_certs: false ... diff --git a/tests/playbooks/testing_collections_playbook.yml b/tests/playbooks/testing_collections_playbook.yml index f0a544e..9b7f6eb 100644 --- a/tests/playbooks/testing_collections_playbook.yml +++ b/tests/playbooks/testing_collections_playbook.yml @@ -38,7 +38,7 @@ tags: - assertions vars: - project_lookup: "{{ lookup('infra.eda_configuration.eda_api', 'projects', host=eda_hostname, username=eda_username, + project_lookup: "{{ lookup('ansible.eda.eda_api', 'projects', host=eda_hostname, username=eda_username, password=eda_password, verify_ssl=false, query_params=qp) }}" qp: url: 'https://github.com/ansible/event-driven-ansible.git' From 913ed1f2ce502d2b84cd0b0d0bd19d1dabcbed58 Mon Sep 17 00:00:00 2001 From: David Danielsson Date: Fri, 27 Sep 2024 15:22:09 -0500 Subject: [PATCH 2/7] renamed: user_token/README.md -> controller_token/README.md new file: controller_token/defaults/main.yml renamed: user_token/meta/argument_specs.yml -> controller_token/meta/argument_specs.yml renamed: user_token/meta/main.yml -> controller_token/meta/main.yml new file: controller_token/tasks/main.yml renamed: user_token/tests/test.yml -> controller_token/tests/test.yml renamed: user_token/tests/vars/user_tokens.yml -> controller_token/tests/vars/user_tokens.yml modified: dispatch/README.md modified: dispatch/defaults/main.yml modified: dispatch/meta/argument_specs.yml deleted: user_token/defaults/main.yml deleted: user_token/tasks/main.yml modified: ../changelogs/.plugin-cache.yaml modified: ../tests/playbooks/eda_configs/eda_user_tokens.yml --- changelogs/.plugin-cache.yaml | 54 +------------------ .../README.md | 17 +++--- roles/controller_token/defaults/main.yml | 8 +++ .../meta/argument_specs.yml | 8 +-- .../meta/main.yml | 4 +- roles/controller_token/tasks/main.yml | 39 ++++++++++++++ .../tests/test.yml | 2 +- .../tests/vars/user_tokens.yml | 2 +- roles/dispatch/README.md | 2 +- roles/dispatch/defaults/main.yml | 6 +-- roles/dispatch/meta/argument_specs.yml | 2 +- roles/user_token/defaults/main.yml | 8 --- roles/user_token/tasks/main.yml | 40 -------------- .../playbooks/eda_configs/eda_user_tokens.yml | 2 +- 14 files changed, 70 insertions(+), 124 deletions(-) rename roles/{user_token => controller_token}/README.md (76%) create mode 100644 roles/controller_token/defaults/main.yml rename roles/{user_token => controller_token}/meta/argument_specs.yml (92%) rename roles/{user_token => controller_token}/meta/main.yml (95%) create mode 100644 roles/controller_token/tasks/main.yml rename roles/{user_token => controller_token}/tests/test.yml (94%) rename roles/{user_token => controller_token}/tests/vars/user_tokens.yml (78%) delete mode 100644 roles/user_token/defaults/main.yml delete mode 100644 roles/user_token/tasks/main.yml diff --git a/changelogs/.plugin-cache.yaml b/changelogs/.plugin-cache.yaml index ac6084d..e50c9a1 100644 --- a/changelogs/.plugin-cache.yaml +++ b/changelogs/.plugin-cache.yaml @@ -29,59 +29,9 @@ objects: description: An Ansible Role to create users in EDA controller. name: user version_added: null - user_token: + controller_token: description: An Ansible Role to create user tokens in EDA controller. - name: user_token - version_added: null -plugins: - become: {} - cache: {} - callback: {} - cliconf: {} - connection: {} - filter: {} - httpapi: {} - inventory: {} - lookup: - eda_api: - description: Search the API for objects - name: eda_api - version_added: null - module: - credential: - description: Manage a Credential in EDA Controller - name: credential - namespace: '' - version_added: null - decision_environment: - description: Manage a Decision Environment in EDA Controller - name: decision_environment - namespace: '' - version_added: null - project: - description: Manage a project in EDA Controller - name: project - namespace: '' - version_added: null - project_sync: - description: Sync a project in EDA Controller - name: project_sync - namespace: '' - version_added: null - rulebook_activation: - description: Manage a rulebook_activation in EDA Controller - name: rulebook_activation - namespace: '' - version_added: null - user: - description: Manage a user in EDA Controller - name: user - namespace: '' - version_added: null - user_token: - description: Manage the user tokens of the current user in EDA Controller - name: user_token - namespace: '' + name: controller_token version_added: null netconf: {} shell: {} diff --git a/roles/user_token/README.md b/roles/controller_token/README.md similarity index 76% rename from roles/user_token/README.md rename to roles/controller_token/README.md index cc6609c..68b3e6c 100644 --- a/roles/user_token/README.md +++ b/roles/controller_token/README.md @@ -1,4 +1,4 @@ -# ansible.eda.user_token +# infra.eda_configuration.controller_token ## Description @@ -15,18 +15,18 @@ Note that tokens cannot be updated, only created. |`eda_validate_certs`|`False`|no|Whether or not to validate the Ansible EDA Controller Server's SSL certificate.|| |`eda_request_timeout`|`10`|no|Specify the timeout Ansible should use in requests to the EDA Controller host.|| |`eda_configuration_async_dir`|`null`|no|Sets the directory to write the results file for async tasks. The default value is set to `null` which uses the Ansible Default of `/root/.ansible_async/`.|| -|`eda_user_tokens`|`see below`|yes|Data structure describing your user tokens, described below.|| +|`eda_controller_tokens`|`see below`|yes|Data structure describing your user tokens, described below.|| ### Secure Logging Variables The following Variables complement each other. If Both variables are not set, secure logging defaults to false. The role defaults to False as normally the add project task does not include sensitive information. -eda_configuration_user_token_secure_logging defaults to the value of eda_configuration_secure_logging if it is not explicitly called. This allows for secure logging to be toggled for the entire suite of EDA Controller configuration roles with a single variable, or for the user to selectively use it. +eda_configuration_controller_tokenssecure_logging defaults to the value of eda_configuration_secure_logging if it is not explicitly called. This allows for secure logging to be toggled for the entire suite of EDA Controller configuration roles with a single variable, or for the user to selectively use it. |Variable Name|Default Value|Required|Description| |:---:|:---:|:---:|:---:| -|`eda_configuration_user_token_secure_logging`|`False`|no|Whether or not to include the sensitive Project role tasks in the log. Set this value to `True` if you will be providing your sensitive values from elsewhere.| +|`eda_configuration_controller_tokenssecure_logging`|`False`|no|Whether or not to include the sensitive Project role tasks in the log. Set this value to `True` if you will be providing your sensitive values from elsewhere.| |`eda_configuration_secure_logging`|`False`|no|This variable enables secure logging as well, but is shared across multiple roles, see above.| ### Asynchronous Retry Variables @@ -39,9 +39,9 @@ This also speeds up the overall role. |Variable Name|Default Value|Required|Description| |:---:|:---:|:---:|:---:| |`eda_configuration_async_retries`|50|no|This variable sets the number of retries to attempt for the role globally.| -|`eda_configuration_user_token_async_retries`|`eda_configuration_async_retries`|no|This variable sets the number of retries to attempt for the role.| +|`eda_configuration_controller_tokensasync_retries`|`eda_configuration_async_retries`|no|This variable sets the number of retries to attempt for the role.| |`eda_configuration_async_delay`|1|no|This sets the delay between retries for the role globally.| -|`eda_configuration_user_token_async_delay`|`eda_configuration_async_delay`|no|This sets the delay between retries for the role.| +|`eda_configuration_controller_tokensasync_delay`|`eda_configuration_async_delay`|no|This sets the delay between retries for the role.| ## Data Structure @@ -50,7 +50,6 @@ This also speeds up the overall role. |Variable Name|Default Value|Required|Type|Description| |:---:|:---:|:---:|:---:|:---:| |`name`|""|yes|str|User Token name. Must be lower case containing only alphanumeric characters and underscores.| -|`new_name`|""|no|str|Setting this option will change the existing name (looked up via the name field.)| |`description`|""|no|str|Description to use for the Project.| |`token`|""|yes|str|The value of the token to associate with the user.| @@ -60,7 +59,7 @@ This also speeds up the overall role. ```yaml --- -eda_user_tokens: +eda_controller_tokens: - name: my_default_token description: my default user token token: TOKEN_VALUE @@ -89,7 +88,7 @@ eda_user_tokens: tags: - always roles: - - ../../user_token + - infra.eda_configuration.controller_token ``` ## License diff --git a/roles/controller_token/defaults/main.yml b/roles/controller_token/defaults/main.yml new file mode 100644 index 0000000..1450868 --- /dev/null +++ b/roles/controller_token/defaults/main.yml @@ -0,0 +1,8 @@ +--- +eda_controller_tokens: [] + +eda_configuration_controller_tokenssecure_logging: "{{ eda_configuration_secure_logging | default(false) }}" +eda_configuration_controller_tokensasync_retries: "{{ eda_configuration_async_retries | default(50) }}" +eda_configuration_controller_tokensasync_delay: "{{ eda_configuration_async_delay | default(1) }}" +eda_configuration_async_dir: null +... diff --git a/roles/user_token/meta/argument_specs.yml b/roles/controller_token/meta/argument_specs.yml similarity index 92% rename from roles/user_token/meta/argument_specs.yml rename to roles/controller_token/meta/argument_specs.yml index 93f1320..9e27c6a 100644 --- a/roles/user_token/meta/argument_specs.yml +++ b/roles/controller_token/meta/argument_specs.yml @@ -3,7 +3,7 @@ argument_specs: main: short_description: An Ansible Role to create user tokens in EDA controller. options: - eda_user_tokens: + eda_controller_tokens: default: [] required: false description: Data structure describing your user tokens to manage. @@ -11,7 +11,7 @@ argument_specs: elements: dict # Async variables - eda_configuration_user_token_async_retries: + eda_configuration_controller_tokensasync_retries: default: "{{ eda_configuration_async_retries | default(50) }}" required: false description: This variable sets the number of retries to attempt for the role. @@ -19,7 +19,7 @@ argument_specs: default: 50 required: false description: This variable sets number of retries across all roles as a default. - eda_configuration_user_token_async_delay: + eda_configuration_controller_tokensasync_delay: default: "{{ eda_configuration_async_delay | default(1) }}" required: false description: This variable sets delay between retries for the role. @@ -33,7 +33,7 @@ argument_specs: description: Sets the directory to write the results file for async tasks. The default value is set to `null` which uses the Ansible Default of `/root/.ansible_async/`. # No_log variables - eda_configuration_user_token_secure_logging: + eda_configuration_controller_tokenssecure_logging: default: "{{ eda_configuration_secure_logging | default(false) }}" required: false type: bool diff --git a/roles/user_token/meta/main.yml b/roles/controller_token/meta/main.yml similarity index 95% rename from roles/user_token/meta/main.yml rename to roles/controller_token/meta/main.yml index 5e9171b..2c9060f 100644 --- a/roles/user_token/meta/main.yml +++ b/roles/controller_token/meta/main.yml @@ -1,6 +1,6 @@ --- galaxy_info: - role_name: "user_token" + role_name: controller_token author: "Derek Waters" description: "An Ansible Role to create a user token in EDA Controller." company: "Red Hat" @@ -33,8 +33,6 @@ galaxy_info: - "edacontroller" - "eda" - "configuration" - - "user" - - "users" dependencies: [] # List your role dependencies here, one per line. Be sure to remove the '[]' above, diff --git a/roles/controller_token/tasks/main.yml b/roles/controller_token/tasks/main.yml new file mode 100644 index 0000000..ed56e7b --- /dev/null +++ b/roles/controller_token/tasks/main.yml @@ -0,0 +1,39 @@ +--- + +# Create EDA Controller Tokens +- name: Add EDA Controller token + ansible.eda.controller_token: + name: "{{ __token_item.name }}" + description: "{{ __token_item.description | default(omit) }}" + token: "{{ __token_item.token | default(omit) }}" + controller_host: "{{ eda_host | default(eda_hostname) }}" + controller_username: "{{ eda_username | default(omit) }}" + controller_password: "{{ eda_password | default(omit) }}" + validate_certs: "{{ eda_validate_certs | default(omit) }}" + request_timeout: "{{ eda_request_timeout | default(omit) }}" + loop: "{{ eda_controller_tokens }}" + loop_control: + loop_var: "__token_item" + no_log: "{{ eda_configuration_controller_tokenssecure_logging }}" + async: 1000 + poll: 0 + register: __controller_tokens_job_async + changed_when: not __controller_tokens_job_async.changed + vars: + ansible_async_dir: '{{ eda_configuration_async_dir }}' + +- name: "Create controller_token | Wait for finish the controller_token creation" + ansible.builtin.async_status: + jid: "{{ __controller_tokens_job_async_result_item.ansible_job_id }}" + register: __controller_tokens_job_async_result + until: __controller_tokens_job_async_result.finished + retries: "{{ eda_configuration_controller_tokensasync_retries }}" + delay: "{{ eda_configuration_controller_tokensasync_delay }}" + loop: "{{ __controller_tokens_job_async.results }}" + loop_control: + loop_var: __controller_tokens_job_async_result_item + when: __controller_tokens_job_async_result_item.ansible_job_id is defined + no_log: "{{ eda_configuration_controller_tokenssecure_logging }}" + vars: + ansible_async_dir: '{{ eda_configuration_async_dir }}' +... diff --git a/roles/user_token/tests/test.yml b/roles/controller_token/tests/test.yml similarity index 94% rename from roles/user_token/tests/test.yml rename to roles/controller_token/tests/test.yml index a7f934a..3092026 100644 --- a/roles/user_token/tests/test.yml +++ b/roles/controller_token/tests/test.yml @@ -16,5 +16,5 @@ tags: - always roles: - - ../../user_token + - ../../controller_token ... diff --git a/roles/user_token/tests/vars/user_tokens.yml b/roles/controller_token/tests/vars/user_tokens.yml similarity index 78% rename from roles/user_token/tests/vars/user_tokens.yml rename to roles/controller_token/tests/vars/user_tokens.yml index dd23460..0ad5fc1 100644 --- a/roles/user_token/tests/vars/user_tokens.yml +++ b/roles/controller_token/tests/vars/user_tokens.yml @@ -1,5 +1,5 @@ --- -eda_user_tokens: +eda_controller_tokens: - name: my_user_token description: my awesome token token: ABCDEF diff --git a/roles/dispatch/README.md b/roles/dispatch/README.md index b93ca74..94ad6e4 100644 --- a/roles/dispatch/README.md +++ b/roles/dispatch/README.md @@ -16,7 +16,7 @@ Each role has its own variables, for information on those please see each role w eda_configuration_dispatcher_roles: - {role: user, var: eda_users, tags: user} - {role: credential, var: eda_credentials, tags: credential} - - {role: user_token, var: eda_user_tokens, tags: user_token} + - {role: controller_token, var: eda_controller_tokens, tags: controller_token} - {role: project, var: eda_projects, tags: project} - {role: project_sync, var: eda_projects, tags: project_sync} - {role: decision_environment, var: eda_decision_environments, tags: decision_environment} diff --git a/roles/dispatch/defaults/main.yml b/roles/dispatch/defaults/main.yml index 6c638b6..abab902 100644 --- a/roles/dispatch/defaults/main.yml +++ b/roles/dispatch/defaults/main.yml @@ -6,9 +6,9 @@ eda_configuration_dispatcher_roles: - role: credential var: eda_credentials tags: credential - - role: user_token - var: eda_user_tokens - tags: user_token + - role: controller_token + var: eda_controller_tokens + tags: controller_token - role: project var: eda_projects tags: project diff --git a/roles/dispatch/meta/argument_specs.yml b/roles/dispatch/meta/argument_specs.yml index 70e7532..ba0a0df 100644 --- a/roles/dispatch/meta/argument_specs.yml +++ b/roles/dispatch/meta/argument_specs.yml @@ -7,7 +7,7 @@ argument_specs: default: - {role: user, var: eda_users, tags: user} - {role: credential, var: eda_credentials, tags: credential} - - {role: user_token, var: eda_user_tokens, tags: user_token} + - {role: controller_token, var: eda_controller_tokens, tags: controller_token} - {role: project, var: eda_projects, tags: project} - {role: project_sync, var: eda_projects, tags: project_sync} - {role: decision_environment, var: eda_decision_environments, tags: decision_environment} diff --git a/roles/user_token/defaults/main.yml b/roles/user_token/defaults/main.yml deleted file mode 100644 index 225c236..0000000 --- a/roles/user_token/defaults/main.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -eda_user_tokens: [] - -eda_configuration_user_token_secure_logging: "{{ eda_configuration_secure_logging | default(false) }}" -eda_configuration_user_token_async_retries: "{{ eda_configuration_async_retries | default(50) }}" -eda_configuration_user_token_async_delay: "{{ eda_configuration_async_delay | default(1) }}" -eda_configuration_async_dir: null -... diff --git a/roles/user_token/tasks/main.yml b/roles/user_token/tasks/main.yml deleted file mode 100644 index 7404a7b..0000000 --- a/roles/user_token/tasks/main.yml +++ /dev/null @@ -1,40 +0,0 @@ ---- - -# Create EDA Controller User Tokens -- name: Add EDA Controller user token - ansible.eda.user_token: - name: "{{ __token_item.name }}" - new_name: "{{ __token_item.new_name | default(omit) }}" - description: "{{ __token_item.description | default(omit) }}" - token: "{{ __token_item.token | default(omit) }}" - controller_host: "{{ eda_host | default(eda_hostname) }}" - controller_username: "{{ eda_username | default(omit) }}" - controller_password: "{{ eda_password | default(omit) }}" - validate_certs: "{{ eda_validate_certs | default(omit) }}" - request_timeout: "{{ eda_request_timeout | default(omit) }}" - loop: "{{ eda_user_tokens }}" - loop_control: - loop_var: "__token_item" - no_log: "{{ eda_configuration_user_token_secure_logging }}" - async: 1000 - poll: 0 - register: __user_tokens_job_async - changed_when: not __user_tokens_job_async.changed - vars: - ansible_async_dir: '{{ eda_configuration_async_dir }}' - -- name: "Create user_token | Wait for finish the user_token creation" - ansible.builtin.async_status: - jid: "{{ __user_tokens_job_async_result_item.ansible_job_id }}" - register: __user_tokens_job_async_result - until: __user_tokens_job_async_result.finished - retries: "{{ eda_configuration_user_token_async_retries }}" - delay: "{{ eda_configuration_user_token_async_delay }}" - loop: "{{ __user_tokens_job_async.results }}" - loop_control: - loop_var: __user_tokens_job_async_result_item - when: __user_tokens_job_async_result_item.ansible_job_id is defined - no_log: "{{ eda_configuration_user_token_secure_logging }}" - vars: - ansible_async_dir: '{{ eda_configuration_async_dir }}' -... diff --git a/tests/playbooks/eda_configs/eda_user_tokens.yml b/tests/playbooks/eda_configs/eda_user_tokens.yml index dd23460..0ad5fc1 100644 --- a/tests/playbooks/eda_configs/eda_user_tokens.yml +++ b/tests/playbooks/eda_configs/eda_user_tokens.yml @@ -1,5 +1,5 @@ --- -eda_user_tokens: +eda_controller_tokens: - name: my_user_token description: my awesome token token: ABCDEF From b1dceb939c0c31e0451828eb412b75adbe708f0e Mon Sep 17 00:00:00 2001 From: David Danielsson Date: Fri, 27 Sep 2024 15:29:21 -0500 Subject: [PATCH 3/7] modified: controller_token/README.md modified: controller_token/defaults/main.yml modified: controller_token/meta/argument_specs.yml modified: controller_token/tasks/main.yml --- roles/controller_token/README.md | 8 ++++---- roles/controller_token/defaults/main.yml | 6 +++--- roles/controller_token/meta/argument_specs.yml | 6 +++--- roles/controller_token/tasks/main.yml | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/roles/controller_token/README.md b/roles/controller_token/README.md index 68b3e6c..fb73a20 100644 --- a/roles/controller_token/README.md +++ b/roles/controller_token/README.md @@ -22,11 +22,11 @@ Note that tokens cannot be updated, only created. The following Variables complement each other. If Both variables are not set, secure logging defaults to false. The role defaults to False as normally the add project task does not include sensitive information. -eda_configuration_controller_tokenssecure_logging defaults to the value of eda_configuration_secure_logging if it is not explicitly called. This allows for secure logging to be toggled for the entire suite of EDA Controller configuration roles with a single variable, or for the user to selectively use it. +eda_configuration_user_token_secure_logging defaults to the value of eda_configuration_secure_logging if it is not explicitly called. This allows for secure logging to be toggled for the entire suite of EDA Controller configuration roles with a single variable, or for the user to selectively use it. |Variable Name|Default Value|Required|Description| |:---:|:---:|:---:|:---:| -|`eda_configuration_controller_tokenssecure_logging`|`False`|no|Whether or not to include the sensitive Project role tasks in the log. Set this value to `True` if you will be providing your sensitive values from elsewhere.| +|`eda_configuration_user_token_secure_logging`|`False`|no|Whether or not to include the sensitive Project role tasks in the log. Set this value to `True` if you will be providing your sensitive values from elsewhere.| |`eda_configuration_secure_logging`|`False`|no|This variable enables secure logging as well, but is shared across multiple roles, see above.| ### Asynchronous Retry Variables @@ -39,9 +39,9 @@ This also speeds up the overall role. |Variable Name|Default Value|Required|Description| |:---:|:---:|:---:|:---:| |`eda_configuration_async_retries`|50|no|This variable sets the number of retries to attempt for the role globally.| -|`eda_configuration_controller_tokensasync_retries`|`eda_configuration_async_retries`|no|This variable sets the number of retries to attempt for the role.| +|`eda_configuration_user_token_async_retries`|`eda_configuration_async_retries`|no|This variable sets the number of retries to attempt for the role.| |`eda_configuration_async_delay`|1|no|This sets the delay between retries for the role globally.| -|`eda_configuration_controller_tokensasync_delay`|`eda_configuration_async_delay`|no|This sets the delay between retries for the role.| +|`eda_configuration_user_token_async_delay`|`eda_configuration_async_delay`|no|This sets the delay between retries for the role.| ## Data Structure diff --git a/roles/controller_token/defaults/main.yml b/roles/controller_token/defaults/main.yml index 1450868..bddbfe7 100644 --- a/roles/controller_token/defaults/main.yml +++ b/roles/controller_token/defaults/main.yml @@ -1,8 +1,8 @@ --- eda_controller_tokens: [] -eda_configuration_controller_tokenssecure_logging: "{{ eda_configuration_secure_logging | default(false) }}" -eda_configuration_controller_tokensasync_retries: "{{ eda_configuration_async_retries | default(50) }}" -eda_configuration_controller_tokensasync_delay: "{{ eda_configuration_async_delay | default(1) }}" +eda_configuration_user_token_secure_logging: "{{ eda_configuration_secure_logging | default(false) }}" +eda_configuration_user_token_async_retries: "{{ eda_configuration_async_retries | default(50) }}" +eda_configuration_user_token_async_delay: "{{ eda_configuration_async_delay | default(1) }}" eda_configuration_async_dir: null ... diff --git a/roles/controller_token/meta/argument_specs.yml b/roles/controller_token/meta/argument_specs.yml index 9e27c6a..1bef966 100644 --- a/roles/controller_token/meta/argument_specs.yml +++ b/roles/controller_token/meta/argument_specs.yml @@ -11,7 +11,7 @@ argument_specs: elements: dict # Async variables - eda_configuration_controller_tokensasync_retries: + eda_configuration_user_token_async_retries: default: "{{ eda_configuration_async_retries | default(50) }}" required: false description: This variable sets the number of retries to attempt for the role. @@ -19,7 +19,7 @@ argument_specs: default: 50 required: false description: This variable sets number of retries across all roles as a default. - eda_configuration_controller_tokensasync_delay: + eda_configuration_user_token_async_delay: default: "{{ eda_configuration_async_delay | default(1) }}" required: false description: This variable sets delay between retries for the role. @@ -33,7 +33,7 @@ argument_specs: description: Sets the directory to write the results file for async tasks. The default value is set to `null` which uses the Ansible Default of `/root/.ansible_async/`. # No_log variables - eda_configuration_controller_tokenssecure_logging: + eda_configuration_user_token_secure_logging: default: "{{ eda_configuration_secure_logging | default(false) }}" required: false type: bool diff --git a/roles/controller_token/tasks/main.yml b/roles/controller_token/tasks/main.yml index ed56e7b..49971c2 100644 --- a/roles/controller_token/tasks/main.yml +++ b/roles/controller_token/tasks/main.yml @@ -14,7 +14,7 @@ loop: "{{ eda_controller_tokens }}" loop_control: loop_var: "__token_item" - no_log: "{{ eda_configuration_controller_tokenssecure_logging }}" + no_log: "{{ eda_configuration_user_token_secure_logging }}" async: 1000 poll: 0 register: __controller_tokens_job_async @@ -27,13 +27,13 @@ jid: "{{ __controller_tokens_job_async_result_item.ansible_job_id }}" register: __controller_tokens_job_async_result until: __controller_tokens_job_async_result.finished - retries: "{{ eda_configuration_controller_tokensasync_retries }}" - delay: "{{ eda_configuration_controller_tokensasync_delay }}" + retries: "{{ eda_configuration_user_token_async_retries }}" + delay: "{{ eda_configuration_user_token_async_delay }}" loop: "{{ __controller_tokens_job_async.results }}" loop_control: loop_var: __controller_tokens_job_async_result_item when: __controller_tokens_job_async_result_item.ansible_job_id is defined - no_log: "{{ eda_configuration_controller_tokenssecure_logging }}" + no_log: "{{ eda_configuration_user_token_secure_logging }}" vars: ansible_async_dir: '{{ eda_configuration_async_dir }}' ... From add0324bd942f50976fa1c24f7986c329521aa9f Mon Sep 17 00:00:00 2001 From: David Danielsson Date: Fri, 27 Sep 2024 15:32:01 -0500 Subject: [PATCH 4/7] modified: user/README.md --- roles/user/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/user/README.md b/roles/user/README.md index 6e64eb4..a0c07f2 100644 --- a/roles/user/README.md +++ b/roles/user/README.md @@ -1,4 +1,4 @@ -# ansible.eda.user +# infra.eda_configuration.user ## Description From 31d9291984533379525da4da48d8ae6fd5b540c3 Mon Sep 17 00:00:00 2001 From: David Danielsson Date: Fri, 27 Sep 2024 15:38:20 -0500 Subject: [PATCH 5/7] modified: credential/README.md modified: decision_environment/README.md modified: project/README.md --- roles/credential/README.md | 4 ++-- roles/decision_environment/README.md | 2 +- roles/project/README.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/roles/credential/README.md b/roles/credential/README.md index 8805731..3e46627 100644 --- a/roles/credential/README.md +++ b/roles/credential/README.md @@ -51,8 +51,8 @@ This also speeds up the overall role. |`name`|""|yes|str|Credential name. Must be lower case containing only alphanumeric characters and underscores.| |`new_name`|""|no|str|Setting this option will change the existing name (looked up via the name field.)| |`description`|""|no|str|Description to use for the credential.| -|`organization`|""|no|Organization this Credential belongs to.| -|`inputs`|""|no|Credential inputs where the keys are var names used in templating. Refer to the EDA controller documentation for example syntax.| +|`organization`|""|no|str|Organization this Credential belongs to.| +|`inputs`|""|no|dict|Credential inputs where the keys are var names used in templating. Refer to the EDA controller documentation for example syntax.| |`credential_type`|"GitHub Personal Access Token"|yes|str|The type of the credential.| |`state`|`present`|no|str|Desired state of the credential.| diff --git a/roles/decision_environment/README.md b/roles/decision_environment/README.md index e2954df..ef665b1 100644 --- a/roles/decision_environment/README.md +++ b/roles/decision_environment/README.md @@ -53,7 +53,7 @@ This also speeds up the overall role. |`description`|""|no|str|Description to use for the Project.| |`image_url`|""|yes|str|A URL to a a container image to use for the decision environment.| |`credential`|""|no|str|The credential used to access the container registry holding the image.| -|`organization`|""|no|Organization this decision environment belongs to.| +|`organization`|""|no|str|Organization this decision environment belongs to.| |`state`|`present`|no|str|Desired state of the decision environment.| ### Standard Decision Environment Data Structure diff --git a/roles/project/README.md b/roles/project/README.md index 142df1c..57edec8 100644 --- a/roles/project/README.md +++ b/roles/project/README.md @@ -52,7 +52,7 @@ This also speeds up the overall role. |`new_name`|""|no|str|Setting this option will change the existing name (looked up via the name field.)| |`description`|""|no|str|Description to use for the Project.| |`url`|""|yes|str|A URL to a remote archive, such as a Github Release or a build artifact stored in Artifactory and unpacks it into the project path for use. (Alias: scm_url)| -|`organization`|""|no|Organization this project belongs to.| +|`organization`|""|no|str|Organization this project belongs to.| |`credential`|""|no|str|The token needed to utilize the SCM URL.| |`state`|`present`|no|str|Desired state of the project.| From d1e3cb111fd5289c19eaa9eca55c6c9cc453e966 Mon Sep 17 00:00:00 2001 From: David Danielsson Date: Fri, 27 Sep 2024 15:44:37 -0500 Subject: [PATCH 6/7] modified: ../.github/ISSUE_TEMPLATE/bug_report.md --- .github/ISSUE_TEMPLATE/bug_report.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index aa5062b..ef70cab 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -11,15 +11,15 @@ assignees: '' -# Summary +## Summary -# Issue Type +## Issue Type - Bug Report -# Ansible, Collection, Event Driven Ansible Controller details +## Ansible, Collection, Event Driven Ansible Controller details @@ -34,15 +34,15 @@ Event Driven Ansible Controller version - ansible installation method: one of source, pip, OS package, EE -# OS / ENVIRONMENT +## OS / ENVIRONMENT -# Desired Behavior +## Desired Behavior -# Actual Behavior +## Actual Behavior @@ -59,7 +59,7 @@ Include a [minimum complete verifiable example] with: ``` -# STEPS TO REPRODUCE +## STEPS TO REPRODUCE From b72c79a611de97cdba8a8777026ab32e702924a3 Mon Sep 17 00:00:00 2001 From: David Danielsson Date: Fri, 27 Sep 2024 16:25:43 -0500 Subject: [PATCH 7/7] modified: controller_token/tasks/main.yml --- roles/controller_token/tasks/main.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/roles/controller_token/tasks/main.yml b/roles/controller_token/tasks/main.yml index 49971c2..e45866f 100644 --- a/roles/controller_token/tasks/main.yml +++ b/roles/controller_token/tasks/main.yml @@ -3,14 +3,14 @@ # Create EDA Controller Tokens - name: Add EDA Controller token ansible.eda.controller_token: - name: "{{ __token_item.name }}" - description: "{{ __token_item.description | default(omit) }}" - token: "{{ __token_item.token | default(omit) }}" - controller_host: "{{ eda_host | default(eda_hostname) }}" - controller_username: "{{ eda_username | default(omit) }}" - controller_password: "{{ eda_password | default(omit) }}" - validate_certs: "{{ eda_validate_certs | default(omit) }}" - request_timeout: "{{ eda_request_timeout | default(omit) }}" + name: "{{ __token_item.name }}" + description: "{{ __token_item.description | default(omit) }}" + token: "{{ __token_item.token | default(omit) }}" + controller_host: "{{ eda_host | default(eda_hostname) }}" + controller_username: "{{ eda_username | default(omit) }}" + controller_password: "{{ eda_password | default(omit) }}" + validate_certs: "{{ eda_validate_certs | default(omit) }}" + request_timeout: "{{ eda_request_timeout | default(omit) }}" loop: "{{ eda_controller_tokens }}" loop_control: loop_var: "__token_item"