From f0b8fb8ed4ca3a960184a6c38cdae883e5d85eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Aragon=C3=A9s=20Muniesa?= <26822043+ivarmu@users.noreply.github.com> Date: Fri, 7 Apr 2023 05:07:18 +0200 Subject: [PATCH] An inventory source is not ever assigned to an organization (#563) * an inventory source is not ever assigned to an organization * if no organization, no output for organization field --- changelogs/fragments/enforce_defaults.yml | 4 + plugins/lookup/enforce_defaults.py | 74 +++++++++++++++++++ roles/applications/README.md | 16 ++++ roles/applications/defaults/main.yml | 1 + roles/applications/tasks/main.yml | 4 +- .../templates/current_inventory_sources.j2 | 2 + roles/organizations/README.md | 16 ++++ roles/organizations/defaults/main.yml | 1 + roles/organizations/tasks/main.yml | 18 ++--- tests/configs/controller_auth.yml | 1 + 10 files changed, 126 insertions(+), 11 deletions(-) create mode 100644 changelogs/fragments/enforce_defaults.yml create mode 100644 plugins/lookup/enforce_defaults.py diff --git a/changelogs/fragments/enforce_defaults.yml b/changelogs/fragments/enforce_defaults.yml new file mode 100644 index 000000000..1a4ae1cda --- /dev/null +++ b/changelogs/fragments/enforce_defaults.yml @@ -0,0 +1,4 @@ +--- +minor_changes: + - added option to multiple roles to enforce defaults. This is described in each of the roles readmes and will slowly be rolled out to all applicable roles. This option enforces module/api defaults in order to prevent config drift. This makes it so if an option is NOT speficied in a configuration it enforces the default value. It is not enabled by default. +... diff --git a/plugins/lookup/enforce_defaults.py b/plugins/lookup/enforce_defaults.py new file mode 100644 index 000000000..9fbdd71ab --- /dev/null +++ b/plugins/lookup/enforce_defaults.py @@ -0,0 +1,74 @@ +# (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: enforce_defaults +author: "Sean Sullivan (@sean-m-sullivan)" +version_added: "2.3.2" +short_description: Return difference for objects from Controller API +requirements: + - None +description: + - This plugin is used to return what the default value should be depending on conditions. + - If enforce default is true, it will return the default value. Otherwise it will return the omit. + - This is so the value used for the default filter can be turned on and off. +options: + enforce_default: + description: Whether to enforce the default value or use omit. + type: bool + default: False + default_value: + description: + - Value to supply if enforce_default is True. + - This should be empty value or some form of string. + default: '' + omit_value: + description: + - the omit value + type: str + default: '' +""" + +EXAMPLES = """ +- name: Test Filter + ansible.builtin.debug: + msg: "{{ nothing | default(lookup('infra.controller_configuration.enforce_defaults', enforce_default=false , default_value='', omit_value=omit), false) }}" + +""" + +RETURN = """ +_raw: + description: + - Will either return the omit value, or the default value. +""" + +from ansible.plugins.lookup import LookupBase +from ansible.errors import AnsibleError, AnsibleLookupError +from ansible.module_utils._text import to_native +from ansible.utils.display import Display + + +class LookupModule(LookupBase): + display = Display() + + 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): + self.set_options(direct=kwargs) + + # Set Variables for user input + enforce_default = self.get_option("enforce_default") + default_value = self.get_option("default_value") + omit_value = self.get_option("omit_value") + + if enforce_default: + return [default_value] + else: + return [omit_value] diff --git a/roles/applications/README.md b/roles/applications/README.md index 6a620acf1..f2947953c 100644 --- a/roles/applications/README.md +++ b/roles/applications/README.md @@ -26,6 +26,22 @@ Currently: |`controller_oauthtoken`|""|no|Controller Admin User's token on the Ansible Controller Server. This should be stored in an Ansible Vault at or elsewhere and called from a parent playbook. Either username / password or oauthtoken need to be specified.|| |`controller_applications`|`see below`|yes|Data structure describing your applications, described below.|| +### Enforcing defaults + +The following Variables compliment each other. +If Both variables are not set, enforcing default values is not done. +Enabling these variables enforce default values on options that are optional in the controller API. +This should be enabled to enforce configuration and prevent configuration drift. It is recomended to be enabled, however it is not enforced by default. + +Enabling this will enforce configurtion without specifying every option in the configuration files. + +'controller_configuration_applications_enforce_defaults' defaults to the value of 'controller_configuration_enforce_defaults' if it is not explicitly called. This allows for enforced defaults to be toggled for the entire suite of controller configuration roles with a single variable, or for the user to selectively use it. + +|Variable Name|Default Value|Required|Description| +|:---:|:---:|:---:|:---:| +|`controller_configuration_applications_enforce_defaults`|`False`|no|Whether or not to enforce default option values on only the applications role| +|`controller_configuration_enforce_defaults`|`False`|no|This variable enables enforced default values as well, but is shared across multiple roles, see above.| + ### Secure Logging Variables The following Variables compliment each other. diff --git a/roles/applications/defaults/main.yml b/roles/applications/defaults/main.yml index 792d5240c..7eb310a7d 100644 --- a/roles/applications/defaults/main.yml +++ b/roles/applications/defaults/main.yml @@ -4,4 +4,5 @@ controller_applications: [] controller_configuration_applications_secure_logging: "{{ controller_configuration_secure_logging | default('false') }}" controller_configuration_applications_async_retries: "{{ controller_configuration_async_retries | default(30) }}" controller_configuration_applications_async_delay: "{{ controller_configuration_async_delay | default(1) }}" +controller_configuration_applications_enforce_defaults: "{{ controller_configuration_enforce_defaults | default('false') }}" ... diff --git a/roles/applications/tasks/main.yml b/roles/applications/tasks/main.yml index 7169d3830..313abff23 100644 --- a/roles/applications/tasks/main.yml +++ b/roles/applications/tasks/main.yml @@ -5,11 +5,11 @@ name: "{{ __application_item.name | mandatory }}" new_name: "{{ __application_item.new_name | default(omit, true) }}" organization: "{{ __application_item.organization | mandatory }}" - description: "{{ __application_item.description | default(omit, true) }}" + description: "{{ __application_item.description | default(lookup('infra.controller_configuration.enforce_defaults', enforce_default=controller_configuration_applications_enforce_defaults , default_value='', omit_value=omit), true) }}" authorization_grant_type: "{{ __application_item.authorization_grant_type | default('password') }}" client_type: "{{ __application_item.client_type | default('public') }}" redirect_uris: "{{ __application_item.redirect_uris | default([]) }}" - skip_authorization: "{{ __application_item.skip_authorization | default(omit) }}" + skip_authorization: "{{ __application_item.skip_authorization | default(lookup('infra.controller_configuration.enforce_defaults', enforce_default=controller_configuration_applications_enforce_defaults , default_value=false, omit_value=omit), true) }}" state: "{{ __application_item.state | default(controller_state | default('present')) }}" # Role specific options diff --git a/roles/filetree_create/templates/current_inventory_sources.j2 b/roles/filetree_create/templates/current_inventory_sources.j2 index f6d8f258b..5c7887148 100644 --- a/roles/filetree_create/templates/current_inventory_sources.j2 +++ b/roles/filetree_create/templates/current_inventory_sources.j2 @@ -3,7 +3,9 @@ controller_inventory_sources: {% for inventory_source in current_inventory_sources_asset_value %} - name: "{{ inventory_source.name }}" description: "{{ inventory_source.description }}" +{% if inventory_source.summary_fields.organization %} organization: "{{ inventory_source.summary_fields.organization.name }}" +{% endif %} source: "{{ inventory_source.source | default('ToDo: The source of the inventory_source was originally missing and must be specified',true) }}" {% if inventory_source.source_project %} source_project: "{{ inventory_source.summary_fields.source_project.name }}" diff --git a/roles/organizations/README.md b/roles/organizations/README.md index 9a43a43c1..9f3ed6a84 100644 --- a/roles/organizations/README.md +++ b/roles/organizations/README.md @@ -26,6 +26,22 @@ Currently: |`controller_oauthtoken`|""|no|Controller Admin User's token on the Ansible Controller Server. This should be stored in an Ansible Vault at or elsewhere and called from a parent playbook. Either username / password or oauthtoken need to be specified.||| |`controller_organizations`|`see below`|yes|Data structure describing your organization or organizations Described below.|| +### Enforcing defaults + +The following Variables compliment each other. +If Both variables are not set, enforcing default values is not done. +Enabling these variables enforce default values on options that are optional in the controller API. +This should be enabled to enforce configuration and prevent configuration drift. It is recomended to be enabled, however it is not enforced by default. + +Enabling this will enforce configurtion without specifying every option in the configuration files. + +'controller_configuration_organizations_enforce_defaults' defaults to the value of 'controller_configuration_enforce_defaults' if it is not explicitly called. This allows for enforced defaults to be toggled for the entire suite of controller configuration roles with a single variable, or for the user to selectively use it. + +|Variable Name|Default Value|Required|Description| +|:---:|:---:|:---:|:---:| +|`controller_configuration_organizations_enforce_defaults`|`False`|no|Whether or not to enforce default option values on only the applications role| +|`controller_configuration_enforce_defaults`|`False`|no|This variable enables enforced default values as well, but is shared across multiple roles, see above.| + ### Secure Logging Variables The following Variables compliment each other. diff --git a/roles/organizations/defaults/main.yml b/roles/organizations/defaults/main.yml index ab468ed1a..9da400e8c 100644 --- a/roles/organizations/defaults/main.yml +++ b/roles/organizations/defaults/main.yml @@ -3,6 +3,7 @@ controller_organizations: [] controller_configuration_organizations_secure_logging: "{{ controller_configuration_secure_logging | default('false') }}" controller_configuration_organizations_async_retries: "{{ controller_configuration_async_retries | default(30) }}" controller_configuration_organizations_async_delay: "{{ controller_configuration_async_delay | default(1) }}" +controller_configuration_organizations_enforce_defaults: "{{ controller_configuration_enforce_defaults | default('false') }}" assign_galaxy_credentials_to_org: true assign_default_ee_to_org: true ... diff --git a/roles/organizations/tasks/main.yml b/roles/organizations/tasks/main.yml index 1ea03e7a1..53ff7ff71 100644 --- a/roles/organizations/tasks/main.yml +++ b/roles/organizations/tasks/main.yml @@ -2,16 +2,16 @@ - name: Add organizations organization: name: "{{ __controller_organizations_item.name | mandatory }}" - description: "{{ __controller_organizations_item.description | default(omit, true) }}" + description: "{{ __controller_organizations_item.description | default(lookup('infra.controller_configuration.enforce_defaults', enforce_default=controller_configuration_organizations_enforce_defaults , default_value='', omit_value=omit), true) }}" custom_virtualenv: "{{ __controller_organizations_item.custom_virtualenv | default(omit, true) }}" - max_hosts: "{{ __controller_organizations_item.max_hosts | default(omit, true) }}" - instance_groups: "{{ __controller_organizations_item.instance_groups | default(omit, true) }}" - default_environment: "{{ (__controller_organizations_item.default_environment | default(omit)) if (assign_default_ee_to_org is defined and assign_default_ee_to_org) else omit }}" - galaxy_credentials: "{{ (__controller_organizations_item.galaxy_credentials | default(omit)) if (assign_galaxy_credentials_to_org is defined and assign_galaxy_credentials_to_org) else omit }}" - notification_templates_approvals: "{{ __controller_organizations_item.notification_templates_approvals | default(__controller_organizations_item.related.notification_templates_approvals | default([]) | map(attribute='name') | list) | default(omit, true) }}" - notification_templates_started: "{{ __controller_organizations_item.notification_templates_started | default(__controller_organizations_item.related.notification_templates_started | default([]) | map(attribute='name') | list) | default(omit, true) }}" - notification_templates_success: "{{ __controller_organizations_item.notification_templates_success | default(__controller_organizations_item.related.notification_templates_success | default([]) | map(attribute='name') | list) | default(omit, true) }}" - notification_templates_error: "{{ __controller_organizations_item.notification_templates_error | default(__controller_organizations_item.related.notification_templates_error | default([]) | map(attribute='name') | list) | default(omit, true) }}" + max_hosts: "{{ __controller_organizations_item.max_hosts | default(lookup('infra.controller_configuration.enforce_defaults', enforce_default=controller_configuration_organizations_enforce_defaults , default_value=0, omit_value=omit), true) }}" + instance_groups: "{{ __controller_organizations_item.instance_groups | default(lookup('infra.controller_configuration.enforce_defaults', enforce_default=controller_configuration_organizations_enforce_defaults , default_value=[], omit_value=omit), true) }}" + default_environment: "{{ (__controller_organizations_item.default_environment.name | default(__controller_organizations_item.execution_environment | default(omit))) if (assign_default_ee_to_org is defined and assign_default_ee_to_org) else omit }}" + galaxy_credentials: "{{ (__controller_organizations_item.galaxy_credentials | default(lookup('infra.controller_configuration.enforce_defaults', enforce_default=controller_configuration_organizations_enforce_defaults , default_value=[], omit_value=omit), true)) if (assign_galaxy_credentials_to_org is defined and assign_galaxy_credentials_to_org) else omit }}" + notification_templates_approvals: "{{ __controller_organizations_item.notification_templates_approvals | default(__controller_organizations_item.related.notification_templates_approvals | default([]) | map(attribute='name') | list) | default(lookup('infra.controller_configuration.enforce_defaults', enforce_default=controller_configuration_organizations_enforce_defaults , default_value=[], omit_value=omit), true) }}" + notification_templates_started: "{{ __controller_organizations_item.notification_templates_started | default(__controller_organizations_item.related.notification_templates_started | default([]) | map(attribute='name') | list) | default(lookup('infra.controller_configuration.enforce_defaults', enforce_default=controller_configuration_organizations_enforce_defaults , default_value=[], omit_value=omit), true) }}" + notification_templates_success: "{{ __controller_organizations_item.notification_templates_success | default(__controller_organizations_item.related.notification_templates_success | default([]) | map(attribute='name') | list) | default(lookup('infra.controller_configuration.enforce_defaults', enforce_default=controller_configuration_organizations_enforce_defaults , default_value=[], omit_value=omit), true) }}" + notification_templates_error: "{{ __controller_organizations_item.notification_templates_error | default(__controller_organizations_item.related.notification_templates_error | default([]) | map(attribute='name') | list) | default(lookup('infra.controller_configuration.enforce_defaults', enforce_default=controller_configuration_organizations_enforce_defaults , default_value=[], omit_value=omit), true) }}" state: "{{ __controller_organizations_item.state | default(controller_state | default('present')) }}" # Role Standard Options diff --git a/tests/configs/controller_auth.yml b/tests/configs/controller_auth.yml index 354e3050b..3df52670f 100644 --- a/tests/configs/controller_auth.yml +++ b/tests/configs/controller_auth.yml @@ -4,4 +4,5 @@ controller_username: admin controller_password: password controller_validate_certs: false +controller_configuration_enforce_defaults: true ...