From 2f79c153bcdfb18071aecdad1e5fe3c0a42f943b Mon Sep 17 00:00:00 2001 From: ivarmu <26822043+ivarmu@users.noreply.github.com> Date: Tue, 7 Nov 2023 17:22:19 +0100 Subject: [PATCH] all the objects has been updated to let flatten output --- .../filtree_create_flatten_output.yml | 4 + roles/filetree_create/README.md | 1 + roles/filetree_create/tasks/applications.yml | 86 +++++++---- .../tasks/constructed_inventory.yml | 98 +++++++++---- roles/filetree_create/tasks/credentials.yml | 86 +++++++---- roles/filetree_create/tasks/groups.yml | 46 ++++-- roles/filetree_create/tasks/hosts.yml | 46 ++++-- roles/filetree_create/tasks/inventory.yml | 125 ++++++++++++---- .../tasks/inventory_sources.yml | 48 +++++-- roles/filetree_create/tasks/job_templates.yml | 11 +- roles/filetree_create/tasks/labels.yml | 86 +++++++---- .../tasks/notification_templates.yml | 77 +++++++--- roles/filetree_create/tasks/organizations.yml | 112 ++++++++++----- roles/filetree_create/tasks/projects.yml | 116 ++++++++++----- roles/filetree_create/tasks/schedules.yml | 96 +++++++++---- roles/filetree_create/tasks/team_roles.yml | 13 +- roles/filetree_create/tasks/teams.yml | 11 +- roles/filetree_create/tasks/user_roles.yml | 59 ++++++-- roles/filetree_create/tasks/users.yml | 83 +++++++---- .../tasks/workflow_job_templates.yml | 134 ++++++++++++------ .../templates/current_applications.j2 | 4 + .../templates/current_credentials.j2 | 6 + .../templates/current_groups.j2 | 4 + .../templates/current_hosts.j2 | 4 + .../templates/current_inventories.j2 | 4 + .../templates/current_inventory_sources.j2 | 4 + .../templates/current_job_templates.j2 | 6 +- .../templates/current_labels.j2 | 4 + .../current_notification_templates.j2 | 4 + .../templates/current_organizations.j2 | 4 + .../templates/current_projects.j2 | 4 + .../templates/current_schedules.j2 | 4 + .../templates/current_team_roles.j2 | 6 +- .../templates/current_teams.j2 | 4 +- .../templates/current_user_roles.j2 | 4 + .../templates/current_users.j2 | 4 + .../current_workflow_job_templates.j2 | 16 ++- 37 files changed, 1038 insertions(+), 386 deletions(-) create mode 100644 changelogs/fragments/filtree_create_flatten_output.yml diff --git a/changelogs/fragments/filtree_create_flatten_output.yml b/changelogs/fragments/filtree_create_flatten_output.yml new file mode 100644 index 000000000..99529272f --- /dev/null +++ b/changelogs/fragments/filtree_create_flatten_output.yml @@ -0,0 +1,4 @@ +--- +minor_changes: + - The role 'filetree_create' will now allow to export all the objects of one kind into a single file, so it can be loaded by both ansible `group_vars` syntax and `filetree_read` tool. +... diff --git a/roles/filetree_create/README.md b/roles/filetree_create/README.md index cfc66f5e9..98e3f2199 100644 --- a/roles/filetree_create/README.md +++ b/roles/filetree_create/README.md @@ -19,6 +19,7 @@ The following variables are required for that role to work properly: | `organization_id` | N/A | no | int | Alternative to `organization_filter`, but specifiying the current organization's ID to filter by. Exports only the objects belonging to the specified organization (applies to all the objects that can be assigned to an organization). | | `output_path` | `/tmp/filetree_output` | yes | str | The path to the output directory where all the generated `yaml` files with the corresponding Objects as code will be written to. | | `input_tag` | `['all']` | no | List of Strings | The tags which are applied to the 'sub-roles'. If 'all' is in the list (the default value) then all roles will be called. | +| `flatten_output` | N/A | no | bool | Whether to flatten the output in single files per each object type instead of the normal exportation structure | ## Dependencies diff --git a/roles/filetree_create/tasks/applications.yml b/roles/filetree_create/tasks/applications.yml index 5fbcaf85d..df7eb9cbd 100644 --- a/roles/filetree_create/tasks/applications.yml +++ b/roles/filetree_create/tasks/applications.yml @@ -11,32 +11,66 @@ order_by: 'organization,id' no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Create the /applications output directory for applications in {{ output_path }}" - ansible.builtin.file: - path: "{{ __path }}" - state: directory - mode: '0755' +- name: "Block for to generate flatten output" + when: + - flatten_output is defined + - flatten_output | bool vars: - __path: "{{ output_path }}/{{ needed_path | regex_replace('/', '_') }}/applications" - loop: "{{ (applications_lookvar | map(attribute='summary_fields') | selectattr('organization', 'defined') | map(attribute='organization') | map(attribute='name') | list | flatten | unique) - + (['ORGANIZATIONLESS'] if ((applications_lookvar | map(attribute='summary_fields') | selectattr('organization', 'undefined') | list | flatten) | length > 0) else []) - }}" - loop_control: - loop_var: needed_path - label: "{{ __path }}" + __dest: "{{ output_path }}/applications.yaml" + block: + - name: "Add current applications to the applications flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ __dest }}" + marker: "" + block: "{{ lookup('template', 'templates/current_applications.j2') }}" + vars: + application_organization: "{{ current_applications_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS', true) }}" + application_id: "{{ current_applications_asset_value.id }}" + application_name: "{{ current_applications_asset_value.name | regex_replace('/', '_') }}" + last_application: "{{ current_application_index == ((applications_lookvar | length) - 1) }}" + loop: "{{ applications_lookvar }}" + loop_control: + index_var: current_application_index + loop_var: current_applications_asset_value + label: "{{ __dest }}" -- name: "Add current applications to the /applications output file in {{ output_path }}" - ansible.builtin.template: - src: "templates/current_applications.j2" - dest: "{{ __dest }}" - mode: '0644' - vars: - application_organization: "{{ current_applications_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS', true) }}" - application_id: "{{ current_applications_asset_value.id }}" - application_name: "{{ current_applications_asset_value.name | regex_replace('/', '_') }}" - __dest: "{{ output_path }}/{{ application_organization | regex_replace('/', '_') }}/applications/{{ application_id }}_{{ application_name | regex_replace('/', '_') }}.yaml" - loop: "{{ applications_lookvar }}" - loop_control: - loop_var: current_applications_asset_value - label: "{{ __dest }}" + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the /applications output directory for applications in {{ output_path }}" + ansible.builtin.file: + path: "{{ __path }}" + state: directory + mode: '0755' + vars: + __path: "{{ output_path }}/{{ needed_path | regex_replace('/', '_') }}/applications" + loop: "{{ (applications_lookvar | map(attribute='summary_fields') | selectattr('organization', 'defined') | map(attribute='organization') | map(attribute='name') | list | flatten | unique) + + (['ORGANIZATIONLESS'] if ((applications_lookvar | map(attribute='summary_fields') | selectattr('organization', 'undefined') | list | flatten) | length > 0) else []) + }}" + loop_control: + loop_var: needed_path + label: "{{ __path }}" + + - name: "Add current applications to the /applications output file in {{ output_path }}" + ansible.builtin.template: + src: "templates/current_applications.j2" + dest: "{{ __dest }}" + mode: '0644' + vars: + application_organization: "{{ current_applications_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS', true) }}" + application_id: "{{ current_applications_asset_value.id }}" + application_name: "{{ current_applications_asset_value.name | regex_replace('/', '_') }}" + __dest: "{{ output_path }}/{{ application_organization | regex_replace('/', '_') }}/applications/{{ application_id }}_{{ application_name | regex_replace('/', '_') }}.yaml" + loop: "{{ applications_lookvar }}" + loop_control: + loop_var: current_applications_asset_value + label: "{{ __dest }}" ... diff --git a/roles/filetree_create/tasks/constructed_inventory.yml b/roles/filetree_create/tasks/constructed_inventory.yml index 1b35fa374..dc1a2fbaf 100644 --- a/roles/filetree_create/tasks/constructed_inventory.yml +++ b/roles/filetree_create/tasks/constructed_inventory.yml @@ -1,5 +1,5 @@ --- -- name: "Get the inventories from the API" +- name: "Get the constructed inventories from the API" ansible.builtin.set_fact: constructed_inventory_lookvar: "{{ query(controller_api_plugin, 'api/v2/constructed_inventories/', query_params=(query_params | combine({'organization': organization_id})) if organization_id is defined else query_params, @@ -11,31 +11,77 @@ order_by: 'organization,id' no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Create the /inventories output directory for inventories in {{ output_path }}" - ansible.builtin.file: - path: "{{ __path }}" - state: directory - mode: '0755' +- name: "Block for to generate flatten output" + when: + - flatten_output is defined + - flatten_output | bool vars: - inventory_organization: "{{ needed_path.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" - inventory_name: "{{ needed_path.name | regex_replace('/', '_') }}" - __path: "{{ output_path }}/{{ inventory_organization | regex_replace('/', '_') }}/inventories/{{ inventory_name | regex_replace('/', '_') }}" - loop: "{{ constructed_inventory_lookvar }}" - loop_control: - loop_var: needed_path - label: "{{ __path }}" + __dest: "{{ output_path }}/inventories.yaml" + block: + - name: "Stat if the output file exists" + ansible.builtin.stat: + path: "{{ __dest }}" + register: __constructed_inventories_file -- name: "Add current constructed_inventories to the /inventories output yaml file in {{ output_path }}" - ansible.builtin.template: - src: "templates/current_inventories.j2" - dest: "{{ __dest }}" - mode: '0644' - vars: - inventory_organization: "{{ current_inventories_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" - inventory_name: "{{ current_inventories_asset_value.name | regex_replace('/', '_') }}" - __dest: "{{ output_path }}/{{ inventory_organization | regex_replace('/', '_') }}/inventories/{{ inventory_name | regex_replace('/', '_') }}/{{ current_inventories_asset_value.id }}_{{ inventory_name | regex_replace('/', '_') }}.yaml" - loop: "{{ constructed_inventory_lookvar }}" - loop_control: - loop_var: current_inventories_asset_value - label: "{{ __dest }}" + - name: "Remove the yaml finalizer if it's already present" + lineinfile: + path: "{{ __dest }}" + line: "..." + state: absent + when: __constructed_inventories_file.stat.exists | bool + + - name: "Add current constructed inventory to the inventories flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ __dest }}" + marker: "" + block: "{{ lookup('template', 'templates/current_inventories.j2') }}" + vars: + inventory_organization: "{{ current_inventories_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" + inventory_name: "{{ current_inventories_asset_value.name | regex_replace('/', '_') }}" + first_inventory: "{{ not (__constructed_inventories_file.stat.exists | bool) }}" + last_inventory: "{{ current_inventory_index == ((constructed_inventory_lookvar | length) - 1) }}" + loop: "{{ constructed_inventory_lookvar }}" + loop_control: + index_var: current_inventory_index + loop_var: current_inventories_asset_value + label: "{{ __dest }}" + + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the /inventories output directory for inventories in {{ output_path }}" + ansible.builtin.file: + path: "{{ __path }}" + state: directory + mode: '0755' + vars: + inventory_organization: "{{ needed_path.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" + inventory_name: "{{ needed_path.name | regex_replace('/', '_') }}" + __path: "{{ output_path }}/{{ inventory_organization | regex_replace('/', '_') }}/inventories/{{ inventory_name | regex_replace('/', '_') }}" + loop: "{{ constructed_inventory_lookvar }}" + loop_control: + loop_var: needed_path + label: "{{ __path }}" + + - name: "Add current constructed_inventories to the /inventories output yaml file in {{ output_path }}" + ansible.builtin.template: + src: "templates/current_inventories.j2" + dest: "{{ __dest }}" + mode: '0644' + vars: + inventory_organization: "{{ current_inventories_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" + inventory_name: "{{ current_inventories_asset_value.name | regex_replace('/', '_') }}" + __dest: "{{ output_path }}/{{ inventory_organization | regex_replace('/', '_') }}/inventories/{{ inventory_name | regex_replace('/', '_') }}/{{ current_inventories_asset_value.id }}_{{ inventory_name | regex_replace('/', '_') }}.yaml" + loop: "{{ constructed_inventory_lookvar }}" + loop_control: + loop_var: current_inventories_asset_value + label: "{{ __dest }}" ... diff --git a/roles/filetree_create/tasks/credentials.yml b/roles/filetree_create/tasks/credentials.yml index 5647b312b..defb91b04 100644 --- a/roles/filetree_create/tasks/credentials.yml +++ b/roles/filetree_create/tasks/credentials.yml @@ -11,32 +11,66 @@ order_by: 'organization,id' no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Create the /credentials output directory for credentials in {{ output_path }}" - ansible.builtin.file: - path: "{{ __path }}" - state: directory - mode: '0755' +- name: "Block for to generate flatten output" + when: + - flatten_output is defined + - flatten_output | bool vars: - __path: "{{ output_path }}/{{ needed_path }}/credentials" - loop: "{{ (credentials_lookvar | map(attribute='summary_fields') | selectattr('organization', 'defined') | map(attribute='organization') | map(attribute='name') | list | flatten | unique) - + (['ORGANIZATIONLESS'] if ((credentials_lookvar | map(attribute='summary_fields') | selectattr('organization', 'undefined') | list | flatten) | length > 0) else []) - }}" - loop_control: - loop_var: needed_path - label: "{{ __path }}" + __dest: "{{ output_path }}/credentials.yaml" + block: + - name: "Add current credentials to the credentials flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ __dest }}" + marker: "" + block: "{{ lookup('template', 'templates/current_credentials.j2') }}" + vars: + credentials_organization: "{{ current_credentials_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" + credentials_id: "{{ current_credentials_asset_value.id }}" + credentials_name: "{{ current_credentials_asset_value.name | regex_replace('/', '_') }}" + last_credential: "{{ current_credential_index == ((credentials_lookvar | length) - 1) }}" + loop: "{{ credentials_lookvar }}" + loop_control: + index_var: current_credential_index + loop_var: current_credentials_asset_value + label: "{{ __dest }}" -- name: "Add current credentials to the /credentials output yaml file in {{ output_path }}" - ansible.builtin.template: - src: "templates/current_credentials.j2" - dest: "{{ __dest }}" - mode: '0644' - vars: - credentials_organization: "{{ current_credentials_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" - credentials_id: "{{ current_credentials_asset_value.id }}" - credentials_name: "{{ current_credentials_asset_value.name | regex_replace('/', '_') }}" - __dest: "{{ output_path }}/{{ credentials_organization | regex_replace('/', '_') }}/credentials/{{ credentials_id }}_{{ credentials_name | regex_replace('/', '_') }}.yaml" - loop: "{{ credentials_lookvar }}" - loop_control: - loop_var: current_credentials_asset_value - label: "{{ __dest }}" + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the /credentials output directory for credentials in {{ output_path }}" + ansible.builtin.file: + path: "{{ __path }}" + state: directory + mode: '0755' + vars: + __path: "{{ output_path }}/{{ needed_path }}/credentials" + loop: "{{ (credentials_lookvar | map(attribute='summary_fields') | selectattr('organization', 'defined') | map(attribute='organization') | map(attribute='name') | list | flatten | unique) + + (['ORGANIZATIONLESS'] if ((credentials_lookvar | map(attribute='summary_fields') | selectattr('organization', 'undefined') | list | flatten) | length > 0) else []) + }}" + loop_control: + loop_var: needed_path + label: "{{ __path }}" + + - name: "Add current credentials to the /credentials output yaml file in {{ output_path }}" + ansible.builtin.template: + src: "templates/current_credentials.j2" + dest: "{{ __dest }}" + mode: '0644' + vars: + credentials_organization: "{{ current_credentials_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" + credentials_id: "{{ current_credentials_asset_value.id }}" + credentials_name: "{{ current_credentials_asset_value.name | regex_replace('/', '_') }}" + __dest: "{{ output_path }}/{{ credentials_organization | regex_replace('/', '_') }}/credentials/{{ credentials_id }}_{{ credentials_name | regex_replace('/', '_') }}.yaml" + loop: "{{ credentials_lookvar }}" + loop_control: + loop_var: current_credentials_asset_value + label: "{{ __dest }}" ... diff --git a/roles/filetree_create/tasks/groups.yml b/roles/filetree_create/tasks/groups.yml index 529e605b3..e868ac5a7 100644 --- a/roles/filetree_create/tasks/groups.yml +++ b/roles/filetree_create/tasks/groups.yml @@ -1,14 +1,38 @@ --- -- name: "Create the output directory for groups: {{ groups_output_path }}" - ansible.builtin.file: - path: "{{ groups_output_path }}" - state: directory - mode: '0755' +- name: "Block for to generate flatten output" + when: + - flatten_output is defined + - flatten_output | bool + vars: + __dest: "{{ groups_output_path }}" + block: + - name: "Add current groups to the groups flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ __dest }}" + marker: "" + block: "{{ lookup('template', 'templates/current_groups.j2') }}" -- name: "Add current groups to the current_groups.yaml output file in {{ groups_output_path }}" - ansible.builtin.template: - src: "templates/current_groups.j2" - dest: "{{ groups_output_path }}/current_groups.yaml" - mode: '0644' - when: current_groups_asset_value | length > 0 + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the output directory for groups: {{ groups_output_path }}" + ansible.builtin.file: + path: "{{ groups_output_path }}" + state: directory + mode: '0755' + + - name: "Add current groups to the current_groups.yaml output file in {{ groups_output_path }}" + ansible.builtin.template: + src: "templates/current_groups.j2" + dest: "{{ groups_output_path }}/current_groups.yaml" + mode: '0644' + when: current_groups_asset_value | length > 0 ... diff --git a/roles/filetree_create/tasks/hosts.yml b/roles/filetree_create/tasks/hosts.yml index 8ef5a38f5..aac7b35a7 100644 --- a/roles/filetree_create/tasks/hosts.yml +++ b/roles/filetree_create/tasks/hosts.yml @@ -1,14 +1,38 @@ --- -- name: "Create the output directory for hosts: {{ hosts_output_path }}" - ansible.builtin.file: - path: "{{ hosts_output_path }}" - state: directory - mode: '0755' +- name: "Block for to generate flatten output" + when: + - flatten_output is defined + - flatten_output | bool + vars: + __dest: "{{ hosts_output_path }}" + block: + - name: "Add current hosts to the hosts flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ __dest }}" + marker: "" + block: "{{ lookup('template', 'templates/current_hosts.j2') }}" -- name: "Add current hosts to the current_hosts.yaml output file in {{ hosts_output_path }}" - ansible.builtin.template: - src: "templates/current_hosts.j2" - dest: "{{ hosts_output_path }}/current_hosts.yaml" - mode: '0644' - when: current_hosts_asset_value | length > 0 + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the output directory for hosts: {{ hosts_output_path }}" + ansible.builtin.file: + path: "{{ hosts_output_path }}" + state: directory + mode: '0755' + + - name: "Add current hosts to the current_hosts.yaml output file in {{ hosts_output_path }}" + ansible.builtin.template: + src: "templates/current_hosts.j2" + dest: "{{ hosts_output_path }}/current_hosts.yaml" + mode: '0644' + when: current_hosts_asset_value | length > 0 ... diff --git a/roles/filetree_create/tasks/inventory.yml b/roles/filetree_create/tasks/inventory.yml index 93f5e0d86..e0708dd39 100644 --- a/roles/filetree_create/tasks/inventory.yml +++ b/roles/filetree_create/tasks/inventory.yml @@ -12,47 +12,98 @@ order_by: 'organization,id' no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Create the /inventories output directory for inventories in {{ output_path }}" - ansible.builtin.file: - path: "{{ __path }}" - state: directory - mode: '0755' +- name: "Block for to generate flatten output" + when: + - flatten_output is defined + - flatten_output | bool vars: - inventory_organization: "{{ needed_path.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" - inventory_name: "{{ needed_path.name | regex_replace('/', '_') }}" - __path: "{{ output_path }}/{{ inventory_organization | regex_replace('/', '_') }}/inventories/{{ inventory_name | regex_replace('/', '_') }}" - loop: "{{ inventory_lookvar }}" - loop_control: - loop_var: needed_path - label: "{{ __path }}" + __dest: "{{ output_path }}/inventories.yaml" + block: + - name: "Stat if the output file exists" + ansible.builtin.stat: + path: "{{ __dest }}" + register: __inventories_file -- name: "Add current inventories to the /inventories output yaml file in {{ output_path }}" - ansible.builtin.template: - src: "templates/current_inventories.j2" - dest: "{{ __dest }}" - mode: '0644' - vars: - inventory_organization: "{{ current_inventories_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" - inventory_name: "{{ current_inventories_asset_value.name | regex_replace('/', '_') }}" - __dest: "{{ output_path }}/{{ inventory_organization | regex_replace('/', '_') }}/inventories/{{ inventory_name | regex_replace('/', '_') }}/{{ current_inventories_asset_value.id }}_{{ inventory_name | regex_replace('/', '_') }}.yaml" - loop: "{{ inventory_lookvar }}" - loop_control: - loop_var: current_inventories_asset_value - label: "{{ __dest }}" + - name: "Remove the yaml finalizer if it's already present" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: "..." + state: absent + when: __inventories_file.stat.exists | bool + + - name: "Add current inventories to the inventories flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ __dest }}" + marker: '' + block: "{{ lookup('template', 'templates/current_inventories.j2') }}" + vars: + inventory_organization: "{{ current_inventories_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" + inventory_name: "{{ current_inventories_asset_value.name | regex_replace('/', '_') }}" + first_inventory: "{{ not (__inventories_file.stat.exists | bool) }}" + last_inventory: "{{ current_inventory_index == ((inventory_lookvar | length) - 1) }}" + loop: "{{ inventory_lookvar }}" + loop_control: + index_var: current_inventory_index + loop_var: current_inventories_asset_value + label: "{{ __dest }}" + + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the /inventories output directory for inventories in {{ output_path }}" + ansible.builtin.file: + path: "{{ __path }}" + state: directory + mode: '0755' + vars: + inventory_organization: "{{ needed_path.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" + inventory_name: "{{ needed_path.name | regex_replace('/', '_') }}" + __path: "{{ output_path }}/{{ inventory_organization | regex_replace('/', '_') }}/inventories/{{ inventory_name | regex_replace('/', '_') }}" + loop: "{{ inventory_lookvar }}" + loop_control: + loop_var: needed_path + label: "{{ __path }}" + + - name: "Add current inventories to the /inventories output yaml file in {{ output_path }}" + ansible.builtin.template: + src: "templates/current_inventories.j2" + dest: "{{ __dest }}" + mode: '0644' + vars: + inventory_organization: "{{ current_inventories_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" + inventory_name: "{{ current_inventories_asset_value.name | regex_replace('/', '_') }}" + __dest: "{{ output_path }}/{{ inventory_organization | regex_replace('/', '_') }}/inventories/{{ inventory_name | regex_replace('/', '_') }}/{{ current_inventories_asset_value.id }}_{{ inventory_name | regex_replace('/', '_') }}.yaml" + loop: "{{ inventory_lookvar }}" + loop_control: + loop_var: current_inventories_asset_value + label: "{{ __dest }}" - name: "Set the inventory's inventory sources" ansible.builtin.include_tasks: "inventory_sources.yml" vars: inventory_organization: "{{ current_inventory_sources.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" inventory_name: "{{ current_inventory_sources.name | regex_replace('/', '_') }}" - inventory_sources_output_path: "{{ output_path }}/{{ inventory_organization | regex_replace('/', '_') }}/inventories/{{ inventory_name | regex_replace('/', '_') }}" + inventory_sources_output_path: "{{ (output_path + '/' + inventory_organization | regex_replace('/', '_') + '/inventories/' + inventory_name | regex_replace('/', '_')) + if (flatten_output is not defined or (flatten_output | bool) == false) + else + output_path + '/inventory_sources.yaml' }}" current_inventory_sources_asset_value: "{{ query(controller_api_plugin, current_inventory_sources.related.inventory_sources, host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, return_all=true, max_objects=query_controller_api_max_objects) if current_inventory_sources.has_inventory_sources else [] }}" + last_inventory: "{{ current_inventory_index == ((inventory_lookvar | length) - 1) }}" loop: "{{ inventory_lookvar }}" loop_control: + index_var: current_inventory_index loop_var: current_inventory_sources label: "{{ inventory_sources_output_path }}" no_log: "{{ controller_configuration_filetree_create_secure_logging }}" @@ -62,14 +113,20 @@ vars: inventory_organization: "{{ current_inventory_hosts.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" inventory_name: "{{ current_inventory_hosts.name | regex_replace('/', '_') }}" - hosts_output_path: "{{ output_path }}/{{ inventory_organization | regex_replace('/', '_') }}/inventories/{{ inventory_name | regex_replace('/', '_') }}" + hosts_output_path: "{{ (output_path + '/' + inventory_organization | regex_replace('/', '_') + '/inventories/' + inventory_name | regex_replace('/', '_')) + if (flatten_output is not defined or (flatten_output | bool) == false) + else + output_path + '/hosts.yaml' }}" current_hosts_asset_value: "{{ query(controller_api_plugin, current_inventory_hosts.related.hosts, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) - if not current_inventory_hosts.has_inventory_sources else [] + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) + if not current_inventory_hosts.has_inventory_sources else [] }}" + first_inventory: "{{ not (__inventories_file.stat.exists | bool) }}" + last_inventory: "{{ current_inventory_index == ((inventory_lookvar | length) - 1) }}" loop: "{{ inventory_lookvar }}" loop_control: + index_var: current_inventory_index loop_var: current_inventory_hosts label: "{{ hosts_output_path }}" no_log: "{{ controller_configuration_filetree_create_secure_logging }}" @@ -80,14 +137,20 @@ vars: inventory_organization: "{{ current_inventory_groups.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" inventory_name: "{{ current_inventory_groups.name | regex_replace('/', '_') }}" - groups_output_path: "{{ output_path }}/{{ inventory_organization | regex_replace('/', '_') }}/inventories/{{ inventory_name | regex_replace('/', '_') }}" + groups_output_path: "{{ (output_path + '/' + inventory_organization | regex_replace('/', '_') + '/inventories/' + inventory_name | regex_replace('/', '_')) + if (flatten_output is not defined or (flatten_output | bool) == false) + else + output_path + '/groups.yaml' }}" current_groups_asset_value: "{{ query(controller_api_plugin, current_inventory_groups.related.groups, host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, return_all=true, max_objects=query_controller_api_max_objects) if (not current_inventory_groups.has_inventory_sources or current_inventory_groups.kind is match('smart')) else [] }}" + first_inventory: "{{ not (__inventories_file.stat.exists | bool) }}" + last_inventory: "{{ current_inventory_index == ((inventory_lookvar | length) - 1) }}" loop: "{{ inventory_lookvar }}" loop_control: + index_var: current_inventory_index loop_var: current_inventory_groups label: "{{ groups_output_path }}" no_log: "{{ controller_configuration_filetree_create_secure_logging }}" diff --git a/roles/filetree_create/tasks/inventory_sources.yml b/roles/filetree_create/tasks/inventory_sources.yml index 5092d2ee6..aae7d80ae 100644 --- a/roles/filetree_create/tasks/inventory_sources.yml +++ b/roles/filetree_create/tasks/inventory_sources.yml @@ -1,15 +1,39 @@ --- -- name: "Create the output directory for inventory sources: {{ inventory_sources_output_path }}" - ansible.builtin.file: - path: "{{ inventory_sources_output_path }}" - state: directory - mode: '0755' - -- name: "Add current inventory source to the current_inventory_sources.yaml output file in {{ inventory_sources_output_path }}" - ansible.builtin.template: - src: "templates/current_inventory_sources.j2" - dest: "{{ inventory_sources_output_path }}/current_inventory_sources.yaml" - mode: '0644' +- name: "Block for to generate flatten output" when: - - current_inventory_sources_asset_value | length > 0 + - flatten_output is defined + - flatten_output | bool + block: + - name: "Add current inventory source to the inventory sources flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ inventory_sources_output_path }}" + marker: "" + block: "{{ lookup('template', 'templates/current_inventory_sources.j2') }}" + vars: + last_inventory: "{{ current_inventory_for_sources_index == ((inventory_lookvar | length) - 1) }}" + + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ inventory_sources_output_path }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the output directory for inventory sources: {{ inventory_sources_output_path }}" + ansible.builtin.file: + path: "{{ inventory_sources_output_path }}" + state: directory + mode: '0755' + + - name: "Add current inventory source to the current_inventory_sources.yaml output file in {{ inventory_sources_output_path }}" + ansible.builtin.template: + src: "templates/current_inventory_sources.j2" + dest: "{{ inventory_sources_output_path }}/current_inventory_sources.yaml" + mode: '0644' + when: + - current_inventory_sources_asset_value | length > 0 ... diff --git a/roles/filetree_create/tasks/job_templates.yml b/roles/filetree_create/tasks/job_templates.yml index 191c37f8a..c49b34b5f 100644 --- a/roles/filetree_create/tasks/job_templates.yml +++ b/roles/filetree_create/tasks/job_templates.yml @@ -15,9 +15,11 @@ when: - flatten_output is defined - flatten_output | bool + vars: + __dest: "{{ output_path }}/job_templates.yaml" block: - name: "Add current job_templates to the job_templates flat file" - blockinfile: + ansible.builtin.blockinfile: create: true insertafter: EOF path: "{{ __dest }}" @@ -27,7 +29,6 @@ job_template_organization: "{{ current_job_templates_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" job_template_id: "{{ current_job_templates_asset_value.id }}" job_template_name: "{{ current_job_templates_asset_value.name | regex_replace('/', '_') }}" - __dest: "{{ output_path }}/job_templates.yaml" query_labels: "{{ query(controller_api_plugin, current_job_templates_asset_value.related.labels, host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, return_all=true, max_objects=query_controller_api_max_objects) }}" @@ -48,6 +49,12 @@ label: "{{ __dest }}" no_log: "{{ controller_configuration_filetree_create_secure_logging }}" + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + - name: "Block for to generate the filetre_create normal output" when: flatten_output is not defined or (flatten_output | bool) == false block: diff --git a/roles/filetree_create/tasks/labels.yml b/roles/filetree_create/tasks/labels.yml index db9f44fcc..b8976eced 100644 --- a/roles/filetree_create/tasks/labels.yml +++ b/roles/filetree_create/tasks/labels.yml @@ -11,32 +11,66 @@ order_by: 'organization,id' no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Create the /labels output directory for labels in {{ output_path }}" - ansible.builtin.file: - path: "{{ __path }}" - state: directory - mode: '0755' +- name: "Block for to generate flatten output" + when: + - flatten_output is defined + - flatten_output | bool vars: - __path: "{{ output_path }}/{{ needed_path | regex_replace('/', '_') }}/labels" - loop: "{{ (labels_lookvar | map(attribute='summary_fields') | selectattr('organization', 'defined') | map(attribute='organization') | map(attribute='name') | list | flatten | unique) - + (['ORGANIZATIONLESS'] if ((labels_lookvar | map(attribute='summary_fields') | selectattr('organization', 'undefined') | list | flatten) | length > 0) else []) - }}" - loop_control: - loop_var: needed_path - label: "{{ __path }}" + __dest: "{{ output_path }}/labels.yaml" + block: + - name: "Add current labels to the labels flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ __dest }}" + marker: "" + block: "{{ lookup('template', 'templates/current_labels.j2') }}" + vars: + label_organization: "{{ current_labels_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS', true) }}" + label_id: "{{ current_labels_asset_value.id }}" + label_name: "{{ current_labels_asset_value.name | regex_replace('/', '_') }}" + last_label: "{{ current_label_index == ((labels_lookvar | length) - 1) }}" + loop: "{{ labels_lookvar }}" + loop_control: + index_var: current_label_index + loop_var: current_labels_asset_value + label: "{{ __dest }}" -- name: "Add current labels to the /labels output file in {{ output_path }}" - ansible.builtin.template: - src: "templates/current_labels.j2" - dest: "{{ __dest }}" - mode: '0644' - vars: - label_organization: "{{ current_labels_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS', true) }}" - label_id: "{{ current_labels_asset_value.id }}" - label_name: "{{ current_labels_asset_value.name | regex_replace('/', '_') }}" - __dest: "{{ output_path }}/{{ label_organization | regex_replace('/', '_') }}/labels/{{ label_id }}_{{ label_name | regex_replace('/', '_') }}.yaml" - loop: "{{ labels_lookvar }}" - loop_control: - loop_var: current_labels_asset_value - label: "{{ __dest }}" + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the /labels output directory for labels in {{ output_path }}" + ansible.builtin.file: + path: "{{ __path }}" + state: directory + mode: '0755' + vars: + __path: "{{ output_path }}/{{ needed_path | regex_replace('/', '_') }}/labels" + loop: "{{ (labels_lookvar | map(attribute='summary_fields') | selectattr('organization', 'defined') | map(attribute='organization') | map(attribute='name') | list | flatten | unique) + + (['ORGANIZATIONLESS'] if ((labels_lookvar | map(attribute='summary_fields') | selectattr('organization', 'undefined') | list | flatten) | length > 0) else []) + }}" + loop_control: + loop_var: needed_path + label: "{{ __path }}" + + - name: "Add current labels to the /labels output file in {{ output_path }}" + ansible.builtin.template: + src: "templates/current_labels.j2" + dest: "{{ __dest }}" + mode: '0644' + vars: + label_organization: "{{ current_labels_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS', true) }}" + label_id: "{{ current_labels_asset_value.id }}" + label_name: "{{ current_labels_asset_value.name | regex_replace('/', '_') }}" + __dest: "{{ output_path }}/{{ label_organization | regex_replace('/', '_') }}/labels/{{ label_id }}_{{ label_name | regex_replace('/', '_') }}.yaml" + loop: "{{ labels_lookvar }}" + loop_control: + loop_var: current_labels_asset_value + label: "{{ __dest }}" ... diff --git a/roles/filetree_create/tasks/notification_templates.yml b/roles/filetree_create/tasks/notification_templates.yml index 20e87e11b..2a6edd8a0 100644 --- a/roles/filetree_create/tasks/notification_templates.yml +++ b/roles/filetree_create/tasks/notification_templates.yml @@ -11,29 +11,60 @@ order_by: 'organization,id' no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Create the /notification_templates output directory for notification templates in {{ output_path }}" - ansible.builtin.file: - path: "{{ __path }}" - state: directory - mode: '0755' +- name: "Block for to generate flatten output" + when: + - flatten_output is defined + - flatten_output | bool vars: - __path: "{{ output_path }}/{{ needed_path | regex_replace('/', '_') }}/notification_templates" - loop: "{{ (notification_templates_lookvar | map(attribute='summary_fields') | selectattr('organization', 'defined') | map(attribute='organization') | map(attribute='name') | list | flatten | unique) - + (['ORGANIZATIONLESS'] if ((notification_templates_lookvar | map(attribute='summary_fields') | selectattr('organization', 'undefined') | list | flatten) | length > 0) else []) - }}" - loop_control: - loop_var: needed_path - label: "{{ __path }}" + __dest: "{{ output_path }}/notification_templates.yaml" + block: + - name: "Add current notification_templates to the notification_templates flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ __dest }}" + marker: "" + block: "{{ lookup('template', 'templates/current_notification_templates.j2') }}" + vars: + last_notification_template: "{{ current_notification_template_index == ((notification_templates_lookvar | length) - 1) }}" + loop: "{{ notification_templates_lookvar }}" + loop_control: + index_var: current_notification_template_index + loop_var: current_notification_templates_asset_value + label: "{{ __dest }}" -- name: "Add current notification templates to the /current_notification_templates.yaml output file in {{ output_path }}" - ansible.builtin.template: - src: "templates/current_notification_templates.j2" - dest: "{{ __dest }}" - mode: '0644' - vars: - __dest: "{{ output_path }}/{{ (current_notification_templates_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS', true)) | regex_replace('/', '_') }}/notification_templates/{{ current_notification_templates_asset_value.name | regex_replace('/', '_') }}.yaml" - loop: "{{ notification_templates_lookvar }}" - loop_control: - loop_var: current_notification_templates_asset_value - label: "{{ __dest }}" + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the /notification_templates output directory for notification templates in {{ output_path }}" + ansible.builtin.file: + path: "{{ __path }}" + state: directory + mode: '0755' + vars: + __path: "{{ output_path }}/{{ needed_path | regex_replace('/', '_') }}/notification_templates" + loop: "{{ (notification_templates_lookvar | map(attribute='summary_fields') | selectattr('organization', 'defined') | map(attribute='organization') | map(attribute='name') | list | flatten | unique) + + (['ORGANIZATIONLESS'] if ((notification_templates_lookvar | map(attribute='summary_fields') | selectattr('organization', 'undefined') | list | flatten) | length > 0) else []) + }}" + loop_control: + loop_var: needed_path + label: "{{ __path }}" + + - name: "Add current notification templates to the /current_notification_templates.yaml output file in {{ output_path }}" + ansible.builtin.template: + src: "templates/current_notification_templates.j2" + dest: "{{ __dest }}" + mode: '0644' + vars: + __dest: "{{ output_path }}/{{ (current_notification_templates_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS', true)) | regex_replace('/', '_') }}/notification_templates/{{ current_notification_templates_asset_value.name | regex_replace('/', '_') }}.yaml" + loop: "{{ notification_templates_lookvar }}" + loop_control: + loop_var: current_notification_templates_asset_value + label: "{{ __dest }}" ... diff --git a/roles/filetree_create/tasks/organizations.yml b/roles/filetree_create/tasks/organizations.yml index 54c2f0266..c34c119c0 100644 --- a/roles/filetree_create/tasks/organizations.yml +++ b/roles/filetree_create/tasks/organizations.yml @@ -11,40 +11,84 @@ order_by: 'id' no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Create the output directory for organizations: {{ output_path + '/' + current_organization_dir.name }}" - ansible.builtin.file: - path: "{{ __path }}" - state: directory - mode: '0755' +- name: "Block for to generate flatten output" + when: + - flatten_output is defined + - flatten_output | bool vars: - __path: "{{ output_path }}/{{ current_organization_dir.name | regex_replace('/', '_') }}" - loop: "{{ orgs_lookvar }}" - loop_control: - loop_var: current_organization_dir - label: "{{ __path }}" + __dest: "{{ output_path }}/organizations.yaml" + block: + - name: "Add current organizations to the organizations flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ __dest }}" + marker: "" + block: "{{ lookup('template', 'templates/current_organizations.j2') }}" + vars: + query_notification_error: "{{ query(controller_api_plugin, current_organization.related.notification_templates_error, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_started: "{{ query(controller_api_plugin, current_organization.related.notification_templates_started, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_success: "{{ query(controller_api_plugin, current_organization.related.notification_templates_success, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_approvals: "{{ query(controller_api_plugin, current_organization.related.notification_templates_approvals, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + last_organization: "{{ current_organization_index == ((orgs_lookvar | length) - 1) }}" + loop: "{{ orgs_lookvar }}" + loop_control: + index_var: current_organization_index + loop_var: current_organization + label: "{{ __dest }}" + no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Add current organizations to the output yaml file" - ansible.builtin.template: - src: "templates/current_organizations.j2" - dest: "{{ __dest }}" - mode: '0644' - vars: - __dest: "{{ output_path }}/{{ current_organization.name | regex_replace('/', '_') }}/current_organization.yaml" - query_notification_error: "{{ query(controller_api_plugin, current_organization.related.notification_templates_error, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) }}" - query_notification_started: "{{ query(controller_api_plugin, current_organization.related.notification_templates_started, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) }}" - query_notification_success: "{{ query(controller_api_plugin, current_organization.related.notification_templates_success, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) }}" - query_notification_approvals: "{{ query(controller_api_plugin, current_organization.related.notification_templates_approvals, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) }}" - loop: "{{ orgs_lookvar }}" - loop_control: - loop_var: current_organization - label: "{{ __dest }}" - no_log: "{{ controller_configuration_filetree_create_secure_logging }}" + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the output directory for organizations: {{ output_path + '/' + current_organization_dir.name }}" + ansible.builtin.file: + path: "{{ __path }}" + state: directory + mode: '0755' + vars: + __path: "{{ output_path }}/{{ current_organization_dir.name | regex_replace('/', '_') }}" + loop: "{{ orgs_lookvar }}" + loop_control: + loop_var: current_organization_dir + label: "{{ __path }}" + + - name: "Add current organizations to the output yaml file" + ansible.builtin.template: + src: "templates/current_organizations.j2" + dest: "{{ __dest }}" + mode: '0644' + vars: + __dest: "{{ output_path }}/{{ current_organization.name | regex_replace('/', '_') }}/current_organization.yaml" + query_notification_error: "{{ query(controller_api_plugin, current_organization.related.notification_templates_error, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_started: "{{ query(controller_api_plugin, current_organization.related.notification_templates_started, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_success: "{{ query(controller_api_plugin, current_organization.related.notification_templates_success, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_approvals: "{{ query(controller_api_plugin, current_organization.related.notification_templates_approvals, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + loop: "{{ orgs_lookvar }}" + loop_control: + loop_var: current_organization + label: "{{ __dest }}" + no_log: "{{ controller_configuration_filetree_create_secure_logging }}" ... diff --git a/roles/filetree_create/tasks/projects.yml b/roles/filetree_create/tasks/projects.yml index 5bbcfeca6..69710f79a 100644 --- a/roles/filetree_create/tasks/projects.yml +++ b/roles/filetree_create/tasks/projects.yml @@ -11,42 +11,86 @@ order_by: 'organization,id' no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Create the /projects output directory for projects in {{ output_path }}" - ansible.builtin.file: - path: "{{ __path }}" - state: directory - mode: '0755' +- name: "Block for to generate flatten output" + when: + - flatten_output is defined + - flatten_output | bool vars: - __path: "{{ output_path }}/{{ needed_path | regex_replace('/', '_') }}/projects" - loop: "{{ (projects_lookvar | map(attribute='summary_fields') | selectattr('organization', 'defined') | map(attribute='organization') | map(attribute='name') | list | flatten | unique) - + (['ORGANIZATIONLESS'] if ((projects_lookvar | map(attribute='summary_fields') | selectattr('organization', 'undefined') | list | flatten) | length > 0) else []) - }}" - loop_control: - loop_var: needed_path - label: "{{ __path }}" + __dest: "{{ output_path }}/projects.yaml" + block: + - name: "Add current projects to the projects flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ __dest }}" + marker: "" + block: "{{ lookup('template', 'templates/current_projects.j2') }}" + vars: + project_organization: "{{ current_projects_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS', true) }}" + project_id: "{{ current_projects_asset_value.id }}" + project_name: "{{ current_projects_asset_value.name | regex_replace('/', '_') }}" + query_notification_error: "{{ query(controller_api_plugin, current_projects_asset_value.related.notification_templates_error, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_started: "{{ query(controller_api_plugin, current_projects_asset_value.related.notification_templates_started, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_success: "{{ query(controller_api_plugin, current_projects_asset_value.related.notification_templates_success, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + last_project: "{{ current_project_index == ((projects_lookvar | length) - 1) }}" + loop: "{{ projects_lookvar }}" + loop_control: + index_var: current_project_index + loop_var: current_projects_asset_value + label: "{{ __dest }}" + no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Add current projects to the /projects output file in {{ output_path }}" - ansible.builtin.template: - src: "templates/current_projects.j2" - dest: "{{ __dest }}" - mode: '0644' - vars: - project_organization: "{{ current_projects_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS', true) }}" - project_id: "{{ current_projects_asset_value.id }}" - project_name: "{{ current_projects_asset_value.name | regex_replace('/', '_') }}" - __dest: "{{ output_path }}/{{ project_organization | regex_replace('/', '_') }}/projects/{{ project_id }}_{{ project_name | regex_replace('/', '_') }}.yaml" - query_notification_error: "{{ query(controller_api_plugin, current_projects_asset_value.related.notification_templates_error, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) }}" - query_notification_started: "{{ query(controller_api_plugin, current_projects_asset_value.related.notification_templates_started, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) }}" - query_notification_success: "{{ query(controller_api_plugin, current_projects_asset_value.related.notification_templates_success, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) }}" - loop: "{{ projects_lookvar }}" - loop_control: - loop_var: current_projects_asset_value - label: "{{ __dest }}" - no_log: "{{ controller_configuration_filetree_create_secure_logging }}" + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the /projects output directory for projects in {{ output_path }}" + ansible.builtin.file: + path: "{{ __path }}" + state: directory + mode: '0755' + vars: + __path: "{{ output_path }}/{{ needed_path | regex_replace('/', '_') }}/projects" + loop: "{{ (projects_lookvar | map(attribute='summary_fields') | selectattr('organization', 'defined') | map(attribute='organization') | map(attribute='name') | list | flatten | unique) + + (['ORGANIZATIONLESS'] if ((projects_lookvar | map(attribute='summary_fields') | selectattr('organization', 'undefined') | list | flatten) | length > 0) else []) + }}" + loop_control: + loop_var: needed_path + label: "{{ __path }}" + + - name: "Add current projects to the /projects output file in {{ output_path }}" + ansible.builtin.template: + src: "templates/current_projects.j2" + dest: "{{ __dest }}" + mode: '0644' + vars: + project_organization: "{{ current_projects_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS', true) }}" + project_id: "{{ current_projects_asset_value.id }}" + project_name: "{{ current_projects_asset_value.name | regex_replace('/', '_') }}" + __dest: "{{ output_path }}/{{ project_organization | regex_replace('/', '_') }}/projects/{{ project_id }}_{{ project_name | regex_replace('/', '_') }}.yaml" + query_notification_error: "{{ query(controller_api_plugin, current_projects_asset_value.related.notification_templates_error, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_started: "{{ query(controller_api_plugin, current_projects_asset_value.related.notification_templates_started, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_success: "{{ query(controller_api_plugin, current_projects_asset_value.related.notification_templates_success, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + loop: "{{ projects_lookvar }}" + loop_control: + loop_var: current_projects_asset_value + label: "{{ __dest }}" + no_log: "{{ controller_configuration_filetree_create_secure_logging }}" ... diff --git a/roles/filetree_create/tasks/schedules.yml b/roles/filetree_create/tasks/schedules.yml index 83a110e05..f1dc8f921 100644 --- a/roles/filetree_create/tasks/schedules.yml +++ b/roles/filetree_create/tasks/schedules.yml @@ -7,32 +7,74 @@ }}" no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Create the schedules output directory for schedules in {{ output_path }}" - ansible.builtin.file: - path: "{{ output_path }}/schedules" - state: directory - mode: '0755' - -- name: "Add current schedules to the schedules output file in {{ output_path }}" - ansible.builtin.template: - src: "templates/current_schedules.j2" - dest: "{{ __dest }}" - mode: '0644' +- name: "Block for to generate flatten output" + when: + - flatten_output is defined + - flatten_output | bool vars: - label_id: "{{ current_schedules_asset_value.id }}" - label_name: "{{ current_schedules_asset_value.name | regex_replace('/', '_') }}" - __dest: "{{ output_path }}/schedules/{{ label_id }}_{{ label_name | regex_replace('/', '_') }}.yaml" - query_credentials: "{{ query(controller_api_plugin, current_schedules_asset_value.related.credentials, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) if current_schedules_asset_value.related.credentials is defined else [] }}" - query_instance_groups: "{{ query(controller_api_plugin, current_schedules_asset_value.related.instance_groups, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) if current_schedules_asset_value.related.instance_groups is defined else [] }}" - query_labels: "{{ query(controller_api_plugin, current_schedules_asset_value.related.labels, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) if current_schedules_asset_value.related.labels is defined else [] }}" - loop: "{{ schedules_lookvar }}" - loop_control: - loop_var: current_schedules_asset_value - label: "{{ __dest }}" + __dest: "{{ output_path }}/schedules.yaml" + block: + - name: "Add current schedules to the schedules flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ __dest }}" + marker: "" + block: "{{ lookup('template', 'templates/current_schedules.j2') }}" + vars: + label_id: "{{ current_schedules_asset_value.id }}" + label_name: "{{ current_schedules_asset_value.name | regex_replace('/', '_') }}" + query_credentials: "{{ query(controller_api_plugin, current_schedules_asset_value.related.credentials, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) if current_schedules_asset_value.related.credentials is defined else [] }}" + query_instance_groups: "{{ query(controller_api_plugin, current_schedules_asset_value.related.instance_groups, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) if current_schedules_asset_value.related.instance_groups is defined else [] }}" + query_labels: "{{ query(controller_api_plugin, current_schedules_asset_value.related.labels, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) if current_schedules_asset_value.related.labels is defined else [] }}" + last_schedule: "{{ current_schedule_index == ((schedules_lookvar | length) - 1) }}" + loop: "{{ schedules_lookvar }}" + loop_control: + index_var: current_schedule_index + loop_var: current_schedules_asset_value + label: "{{ __dest }}" + + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the schedules output directory for schedules in {{ output_path }}" + ansible.builtin.file: + path: "{{ output_path }}/schedules" + state: directory + mode: '0755' + + - name: "Add current schedules to the schedules output file in {{ output_path }}" + ansible.builtin.template: + src: "templates/current_schedules.j2" + dest: "{{ __dest }}" + mode: '0644' + vars: + label_id: "{{ current_schedules_asset_value.id }}" + label_name: "{{ current_schedules_asset_value.name | regex_replace('/', '_') }}" + __dest: "{{ output_path }}/schedules/{{ label_id }}_{{ label_name | regex_replace('/', '_') }}.yaml" + query_credentials: "{{ query(controller_api_plugin, current_schedules_asset_value.related.credentials, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) if current_schedules_asset_value.related.credentials is defined else [] }}" + query_instance_groups: "{{ query(controller_api_plugin, current_schedules_asset_value.related.instance_groups, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) if current_schedules_asset_value.related.instance_groups is defined else [] }}" + query_labels: "{{ query(controller_api_plugin, current_schedules_asset_value.related.labels, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) if current_schedules_asset_value.related.labels is defined else [] }}" + loop: "{{ schedules_lookvar }}" + loop_control: + loop_var: current_schedules_asset_value + label: "{{ __dest }}" ... diff --git a/roles/filetree_create/tasks/team_roles.yml b/roles/filetree_create/tasks/team_roles.yml index afb5764b6..760d7c106 100644 --- a/roles/filetree_create/tasks/team_roles.yml +++ b/roles/filetree_create/tasks/team_roles.yml @@ -11,14 +11,16 @@ when: - flatten_output is defined - flatten_output | bool + vars: + __dest: "{{ output_path }}/team_roles.yaml" block: - name: "Stat if the output file exists" ansible.builtin.stat: - path: "{{ output_path }}/team_roles.yaml" + path: "{{ __dest }}" register: team_roles_file - name: "Add current team roles to the team roles flat file" - blockinfile: + ansible.builtin.blockinfile: create: true insertafter: EOF path: "{{ __dest }}" @@ -26,10 +28,15 @@ block: "{{ lookup('template', 'templates/current_team_roles.j2') }}" vars: current_team_roles_asset_value: "{{ team_roles_lookvar }}" - __dest: "{{ output_path }}/team_roles.yaml" first_team_role: "{{ not team_roles_file.stat.exists }}" when: team_roles_lookvar | length > 0 + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + - name: "Block for to generate the filetre_create normal output" when: flatten_output is not defined or (flatten_output | bool) == false block: diff --git a/roles/filetree_create/tasks/teams.yml b/roles/filetree_create/tasks/teams.yml index fb7324d88..bfbe25896 100644 --- a/roles/filetree_create/tasks/teams.yml +++ b/roles/filetree_create/tasks/teams.yml @@ -15,9 +15,11 @@ when: - flatten_output is defined - flatten_output | bool + vars: + __dest: "{{ output_path }}/teams.yaml" block: - name: "Add current teams to the teams flat file" - blockinfile: + ansible.builtin.blockinfile: create: true insertafter: EOF path: "{{ __dest }}" @@ -27,7 +29,6 @@ team_organization: "{{ (current_teams_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS', true)) | regex_replace('/', '_') }}" team_id: "{{ current_teams_asset_value.id }}" team_name: "{{ current_teams_asset_value.name | regex_replace('/', '_') }}" - __dest: "{{ output_path }}/teams.yaml" last_team: "{{ current_team_index == ((teams_lookvar | length) - 1) }}" loop: "{{ teams_lookvar }}" loop_control: @@ -35,6 +36,12 @@ loop_var: current_teams_asset_value label: "{{ __dest }}" + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + - name: "Block for to generate the filetre_create normal output" when: flatten_output is not defined or (flatten_output | bool) == false block: diff --git a/roles/filetree_create/tasks/user_roles.yml b/roles/filetree_create/tasks/user_roles.yml index cd4335327..018d3053d 100644 --- a/roles/filetree_create/tasks/user_roles.yml +++ b/roles/filetree_create/tasks/user_roles.yml @@ -7,18 +7,51 @@ }}" no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Create the output directory for user roles: {{ output_path }}" - ansible.builtin.file: - path: "{{ output_path }}/user_roles" - state: directory - mode: '0755' - -- name: "Add current roles to the output yaml file" - ansible.builtin.template: - src: "templates/current_user_roles.j2" - dest: "{{ output_path }}/user_roles/current_roles_{{ username | regex_replace('/', '_') }}.yaml" - mode: '0644' +- name: "Block for to generate flatten output" + when: + - flatten_output is defined + - flatten_output | bool vars: - current_user_roles_asset_value: "{{ user_roles_lookvar }}" - when: user_roles_lookvar | length > 0 + __dest: "{{ output_path }}/user_roles.yaml" + block: + - name: "Stat if the output file exists" + ansible.builtin.stat: + path: "{{ __dest }}" + register: user_roles_file + + - name: "Add current user roles to the user roles flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ __dest }}" + marker: "" + block: "{{ lookup('template', 'templates/current_user_roles.j2') }}" + vars: + current_user_roles_asset_value: "{{ user_roles_lookvar }}" + first_user_role: "{{ not user_roles_file.stat.exists }}" + when: user_roles_lookvar | length > 0 + + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the output directory for user roles: {{ output_path }}" + ansible.builtin.file: + path: "{{ output_path }}/user_roles" + state: directory + mode: '0755' + + - name: "Add current roles to the output yaml file" + ansible.builtin.template: + src: "templates/current_user_roles.j2" + dest: "{{ output_path }}/user_roles/current_roles_{{ username | regex_replace('/', '_') }}.yaml" + mode: '0644' + vars: + current_user_roles_asset_value: "{{ user_roles_lookvar }}" + when: user_roles_lookvar | length > 0 ... diff --git a/roles/filetree_create/tasks/users.yml b/roles/filetree_create/tasks/users.yml index 79fbbe938..f78c95a21 100644 --- a/roles/filetree_create/tasks/users.yml +++ b/roles/filetree_create/tasks/users.yml @@ -22,41 +22,76 @@ label: "User {{ user_lookvar_item.username }}" no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Create the output directory for users in {{ output_path }}" - ansible.builtin.file: - path: "{{ __path }}" - state: directory - mode: '0755' +- name: "Block for to generate flatten output" + when: + - flatten_output is defined + - flatten_output | bool vars: - __path: "{{ output_path }}/{{ current_user_dir | regex_replace('/', '_') }}/users" - when: organization_filter is not defined or (current_user_dir is match(organization_filter)) - loop: "{{ current_users | selectattr('organizations', 'defined') | map(attribute='organizations') | flatten | unique }}" - loop_control: - loop_var: current_user_dir - label: "{{ __path }}" + __dest: "{{ output_path }}/users.yaml" + block: + - name: "Add current users to the users flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ __dest }}" + marker: "" + block: "{{ lookup('template', 'templates/current_users.j2') }}" + vars: + current_users_asset_value: "{{ current_user_dir.0 }}" + last_user: "{{ current_user_index == ((users_lookvar | length) - 1) }}" + when: organization_filter is not defined or (current_user_dir.1 is match(organization_filter)) + loop: "{{ current_users | default([]) | subelements('organizations', skip_missing=true) }}" + loop_control: + index_var: current_user_index + loop_var: current_user_dir + label: "{{ __dest }}" -- name: "Add current users to the /.yaml output file in {{ output_path }}" - ansible.builtin.template: - src: "templates/current_users.j2" - dest: "{{ __dest }}" - mode: '0644' - vars: - current_users_asset_value: "{{ current_user_dir.0 }}" - __dest: "{{ output_path }}/{{ current_user_dir.1 | regex_replace('/', '_') }}/users/{{ current_user_dir.0.username | regex_replace('/', '_') }}.yaml" - when: organization_filter is not defined or (current_user_dir.1 is match(organization_filter)) - loop: "{{ current_users | default([]) | subelements('organizations', skip_missing=true) }}" - loop_control: - loop_var: current_user_dir - label: "{{ __dest }}" + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the output directory for users in {{ output_path }}" + ansible.builtin.file: + path: "{{ __path }}" + state: directory + mode: '0755' + vars: + __path: "{{ output_path }}/{{ current_user_dir | regex_replace('/', '_') }}/users" + when: organization_filter is not defined or (current_user_dir is match(organization_filter)) + loop: "{{ current_users | selectattr('organizations', 'defined') | map(attribute='organizations') | flatten | unique }}" + loop_control: + loop_var: current_user_dir + label: "{{ __path }}" + + - name: "Add current users to the /.yaml output file in {{ output_path }}" + ansible.builtin.template: + src: "templates/current_users.j2" + dest: "{{ __dest }}" + mode: '0644' + vars: + current_users_asset_value: "{{ current_user_dir.0 }}" + __dest: "{{ output_path }}/{{ current_user_dir.1 | regex_replace('/', '_') }}/users/{{ current_user_dir.0.username | regex_replace('/', '_') }}.yaml" + when: organization_filter is not defined or (current_user_dir.1 is match(organization_filter)) + loop: "{{ current_users | default([]) | subelements('organizations', skip_missing=true) }}" + loop_control: + loop_var: current_user_dir + label: "{{ __dest }}" - name: "Set the user's roles" ansible.builtin.include_tasks: "user_roles.yml" vars: username: "{{ current_user.0.username }}" + last_user_role: "{{ current_user_index_for_roles == ((current_users | default([]) | subelements('organizations', skip_missing=true) | length) - 1) }}" when: - not current_user.0.is_superuser - organization_filter is not defined or (current_user.1 is match(organization_filter)) loop: "{{ current_users | default([]) | subelements('organizations', skip_missing=true) }}" loop_control: + index_var: current_user_index_for_roles loop_var: current_user ... diff --git a/roles/filetree_create/tasks/workflow_job_templates.yml b/roles/filetree_create/tasks/workflow_job_templates.yml index c66d3a156..87901364d 100644 --- a/roles/filetree_create/tasks/workflow_job_templates.yml +++ b/roles/filetree_create/tasks/workflow_job_templates.yml @@ -11,48 +11,98 @@ order_by: 'organization,id' no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Create the /workflow_job_templates output directory for workflow job templates in {{ output_path }}" - ansible.builtin.file: - path: "{{ __path }}" - state: directory - mode: '0755' +- name: "Block for to generate flatten output" + when: + - flatten_output is defined + - flatten_output | bool vars: - __path: "{{ output_path }}/{{ needed_path | regex_replace('/', '_') }}/workflow_job_templates/" - loop: "{{ (workflow_job_templates_lookvar | map(attribute='summary_fields') | selectattr('organization', 'defined') | map(attribute='organization') | map(attribute='name') | list | flatten | unique) - + (['ORGANIZATIONLESS'] if ((workflow_job_templates_lookvar | map(attribute='summary_fields') | selectattr('organization', 'undefined') | list | flatten) | length > 0) else []) - }}" - loop_control: - loop_var: needed_path - label: "{{ __path }}" + __dest: "{{ output_path }}/workflow_job_templates.yaml" + block: + - name: "Add current workflow_job_templates to the workflow_job_templates flat file" + ansible.builtin.blockinfile: + create: true + insertafter: EOF + path: "{{ __dest }}" + marker: "" + block: "{{ lookup('template', 'templates/current_workflow_job_templates.j2') }}" + vars: + workflow_job_template_organization: "{{ current_workflow_job_templates_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" + workflow_job_template_id: "{{ current_workflow_job_templates_asset_value.id }}" + workflow_job_template_name: "{{ current_workflow_job_templates_asset_value.name | regex_replace('/', '_') }}" + query_labels: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.labels, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_error: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.notification_templates_error, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_started: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.notification_templates_started, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_success: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.notification_templates_success, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_approvals: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.notification_templates_approvals, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + last_workflow_job_template: "{{ current_workflow_job_template_index == ((workflow_job_templates_lookvar | length) - 1) }}" + loop: "{{ workflow_job_templates_lookvar }}" + loop_control: + index_var: current_workflow_job_template_index + loop_var: current_workflow_job_templates_asset_value + label: "{{ __dest }}" + no_log: "{{ controller_configuration_filetree_create_secure_logging }}" -- name: "Add current workflow job templates to the /workflow_job_templates output file in {{ output_path }}" - ansible.builtin.template: - src: "templates/current_workflow_job_templates.j2" - dest: "{{ __dest }}" - mode: '0644' - vars: - workflow_job_template_organization: "{{ current_workflow_job_templates_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" - workflow_job_template_id: "{{ current_workflow_job_templates_asset_value.id }}" - workflow_job_template_name: "{{ current_workflow_job_templates_asset_value.name | regex_replace('/', '_') }}" - __dest: "{{ output_path }}/{{ workflow_job_template_organization | regex_replace('/', '_') }}/workflow_job_templates/{{ workflow_job_template_id }}_{{ workflow_job_template_name | regex_replace('/', '_') }}.yaml" - query_labels: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.labels, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) }}" - query_notification_error: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.notification_templates_error, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) }}" - query_notification_started: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.notification_templates_started, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) }}" - query_notification_success: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.notification_templates_success, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) }}" - query_notification_approvals: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.notification_templates_approvals, - host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, - return_all=true, max_objects=query_controller_api_max_objects) }}" - loop: "{{ workflow_job_templates_lookvar }}" - loop_control: - loop_var: current_workflow_job_templates_asset_value - label: "{{ __dest }}" - no_log: "{{ controller_configuration_filetree_create_secure_logging }}" + - name: "Remove all the blank lines introduced by the last task" + ansible.builtin.lineinfile: + path: "{{ __dest }}" + line: '' + state: absent + +- name: "Block for to generate the filetre_create normal output" + when: flatten_output is not defined or (flatten_output | bool) == false + block: + - name: "Create the /workflow_job_templates output directory for workflow job templates in {{ output_path }}" + ansible.builtin.file: + path: "{{ __path }}" + state: directory + mode: '0755' + vars: + __path: "{{ output_path }}/{{ needed_path | regex_replace('/', '_') }}/workflow_job_templates/" + loop: "{{ (workflow_job_templates_lookvar | map(attribute='summary_fields') | selectattr('organization', 'defined') | map(attribute='organization') | map(attribute='name') | list | flatten | unique) + + (['ORGANIZATIONLESS'] if ((workflow_job_templates_lookvar | map(attribute='summary_fields') | selectattr('organization', 'undefined') | list | flatten) | length > 0) else []) + }}" + loop_control: + loop_var: needed_path + label: "{{ __path }}" + + - name: "Add current workflow job templates to the /workflow_job_templates output file in {{ output_path }}" + ansible.builtin.template: + src: "templates/current_workflow_job_templates.j2" + dest: "{{ __dest }}" + mode: '0644' + vars: + workflow_job_template_organization: "{{ current_workflow_job_templates_asset_value.summary_fields.organization.name | default('ORGANIZATIONLESS') }}" + workflow_job_template_id: "{{ current_workflow_job_templates_asset_value.id }}" + workflow_job_template_name: "{{ current_workflow_job_templates_asset_value.name | regex_replace('/', '_') }}" + __dest: "{{ output_path }}/{{ workflow_job_template_organization | regex_replace('/', '_') }}/workflow_job_templates/{{ workflow_job_template_id }}_{{ workflow_job_template_name | regex_replace('/', '_') }}.yaml" + query_labels: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.labels, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_error: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.notification_templates_error, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_started: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.notification_templates_started, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_success: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.notification_templates_success, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + query_notification_approvals: "{{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.notification_templates_approvals, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs, + return_all=true, max_objects=query_controller_api_max_objects) }}" + loop: "{{ workflow_job_templates_lookvar }}" + loop_control: + loop_var: current_workflow_job_templates_asset_value + label: "{{ __dest }}" + no_log: "{{ controller_configuration_filetree_create_secure_logging }}" ... diff --git a/roles/filetree_create/templates/current_applications.j2 b/roles/filetree_create/templates/current_applications.j2 index c27915117..246ba3ed4 100644 --- a/roles/filetree_create/templates/current_applications.j2 +++ b/roles/filetree_create/templates/current_applications.j2 @@ -1,5 +1,7 @@ +{% if (current_application_index | default(0)) == 0 %} --- controller_applications: +{% endif %} - name: "{{ current_applications_asset_value.name }}" description: "{{ current_applications_asset_value.description }}" organization: "{{ current_applications_asset_value.summary_fields.organization.name | default('ToDo: The application \'' + current_applications_asset_value.name + '\' must have an organization') }}" @@ -8,4 +10,6 @@ controller_applications: skip_authorization: "{{ current_applications_asset_value.skip_authorization }}" client_id: "{{ current_applications_asset_value.client_id }}" client_type: "{{ current_applications_asset_value.client_type }}" +{% if last_application | default(true) | bool %} ... +{% endif %} diff --git a/roles/filetree_create/templates/current_credentials.j2 b/roles/filetree_create/templates/current_credentials.j2 index 1eed4841c..d208a5d4e 100644 --- a/roles/filetree_create/templates/current_credentials.j2 +++ b/roles/filetree_create/templates/current_credentials.j2 @@ -1,5 +1,7 @@ +{% if (current_credential_index | default(0)) == 0 %} --- controller_credentials: +{% endif %} - name: "{{ current_credentials_asset_value.name }}" description: "{{ current_credentials_asset_value.description }}" credential_type: "{{ current_credentials_asset_value.summary_fields.credential_type.name }}" @@ -8,6 +10,10 @@ controller_credentials: {% else %} organization: "ORGANIZATIONLESS" {% endif %} +{% if current_credentials_asset_value.inputs is defined and current_credentials_asset_value.inputs is not match('{}') %} inputs: {{ current_credentials_asset_value.inputs | to_nice_yaml(indent=2) | indent(width=6, first=True) | replace("$encrypted$", "\'\'") }} +{% endif %} +{% if last_credential | default(true) | bool %} ... +{% endif %} diff --git a/roles/filetree_create/templates/current_groups.j2 b/roles/filetree_create/templates/current_groups.j2 index de8858bb5..a043e645e 100644 --- a/roles/filetree_create/templates/current_groups.j2 +++ b/roles/filetree_create/templates/current_groups.j2 @@ -1,5 +1,7 @@ +{% if ((first_inventory | default(true) | bool) and ((current_inventory_index | default(0)) == 0)) %} --- controller_groups: +{% endif %} {% for group in current_groups_asset_value %} - name: "{{ group.name }}" description: "{{ group.description }}" @@ -15,4 +17,6 @@ controller_groups: ) | selectattr("name", "defined") | map(attribute="name") | to_nice_yaml(indent=2) | indent(width=6, first=True) }} {%- endfor -%} +{% if last_inventory | default(true) | bool %} ... +{% endif %} diff --git a/roles/filetree_create/templates/current_hosts.j2 b/roles/filetree_create/templates/current_hosts.j2 index 3a3d4abef..7ef807915 100644 --- a/roles/filetree_create/templates/current_hosts.j2 +++ b/roles/filetree_create/templates/current_hosts.j2 @@ -1,5 +1,7 @@ +{% if ((first_inventory | default(true) | bool) and ((current_inventory_index | default(0)) == 0)) %} --- controller_hosts: +{% endif %} {% for host in current_hosts_asset_value if not host.has_inventory_sources %} - name: "{{ host.name }}" description: "{{ host.description }}" @@ -9,4 +11,6 @@ controller_hosts: {{ host.variables | from_yaml | to_nice_yaml(indent=2) | indent(width=6, first=False) | replace("'{{", "!unsafe \'{{") }} {%- endif %} {% endfor %} +{% if last_inventory | default(true) | bool %} ... +{% endif %} diff --git a/roles/filetree_create/templates/current_inventories.j2 b/roles/filetree_create/templates/current_inventories.j2 index e82330541..91c243bc3 100644 --- a/roles/filetree_create/templates/current_inventories.j2 +++ b/roles/filetree_create/templates/current_inventories.j2 @@ -1,5 +1,7 @@ +{% if (first_inventory | default(true) | bool) and (current_inventory_index | default(0) == 0) %} --- controller_inventories: +{% endif %} - name: "{{ current_inventories_asset_value.name }}" description: "{{ current_inventories_asset_value.description }}" organization: "{{ inventory_organization }}" @@ -29,4 +31,6 @@ controller_inventories: variables: {{ current_inventories_asset_value.variables | from_yaml | to_nice_yaml(indent=2) | indent(width=6, first=False) | replace("'{{", "!unsafe \'{{") }} {%- endif %} +{% if last_inventory | default(true) | bool %} ... +{% endif %} diff --git a/roles/filetree_create/templates/current_inventory_sources.j2 b/roles/filetree_create/templates/current_inventory_sources.j2 index 5c7887148..ab1c93936 100644 --- a/roles/filetree_create/templates/current_inventory_sources.j2 +++ b/roles/filetree_create/templates/current_inventory_sources.j2 @@ -1,5 +1,7 @@ +{% if (current_inventory_index | default(0)) == 0 %} --- controller_inventory_sources: +{% endif %} {% for inventory_source in current_inventory_sources_asset_value %} - name: "{{ inventory_source.name }}" description: "{{ inventory_source.description }}" @@ -51,4 +53,6 @@ controller_inventory_sources: {% endfor %} {% endif %} {% endfor %} +{% if last_inventory | default(true) | bool %} ... +{% endif %} diff --git a/roles/filetree_create/templates/current_job_templates.j2 b/roles/filetree_create/templates/current_job_templates.j2 index 031eb5b41..c9c160cbc 100644 --- a/roles/filetree_create/templates/current_job_templates.j2 +++ b/roles/filetree_create/templates/current_job_templates.j2 @@ -1,4 +1,4 @@ -{%- if current_job_template_index == 0 -%} +{% if (current_job_template_index | default(0)) == 0 %} --- controller_templates: {% endif %} @@ -52,7 +52,7 @@ controller_templates: {% if current_job_templates_asset_value.ask_instance_groups_on_launch is defined %} ask_instance_groups_on_launch: {{ current_job_templates_asset_value.ask_instance_groups_on_launch | bool }} {% endif %} -{% if current_job_templates_asset_value.extra_vars and current_job_templates_asset_value.extra_vars != '---' and current_job_templates_asset_value.extra_vars != '' %} +{% if current_job_templates_asset_value.extra_vars and current_job_templates_asset_value.extra_vars | length > 3 %} extra_vars: {{ current_job_templates_asset_value.extra_vars | from_yaml | to_nice_yaml(indent=2) | indent(width=6, first=False) | replace("'{{", "!unsafe \'{{") }} {%- endif %} @@ -110,6 +110,6 @@ controller_templates: {% if current_job_templates_asset_value.prevent_instance_group_fallback is defined %} prevent_instance_group_fallback: {{ current_job_templates_asset_value.prevent_instance_group_fallback | bool }} {% endif %} -{% if last_job_template | bool %} +{% if last_job_template | default(true) | bool %} ... {% endif %} diff --git a/roles/filetree_create/templates/current_labels.j2 b/roles/filetree_create/templates/current_labels.j2 index 727cf90d8..fff70f1a6 100644 --- a/roles/filetree_create/templates/current_labels.j2 +++ b/roles/filetree_create/templates/current_labels.j2 @@ -1,5 +1,9 @@ +{% if (current_label_index | default(0)) == 0 %} --- controller_labels: +{% endif %} - name: "{{ current_labels_asset_value.name }}" organization: "{{ current_labels_asset_value.summary_fields.organization.name | default('ToDo: The label \'' + current_labels_asset_value.name + '\' must have an organization') }}" +{% if last_label | default(true) | bool %} ... +{% endif %} diff --git a/roles/filetree_create/templates/current_notification_templates.j2 b/roles/filetree_create/templates/current_notification_templates.j2 index c98d04497..ad60cb4cc 100644 --- a/roles/filetree_create/templates/current_notification_templates.j2 +++ b/roles/filetree_create/templates/current_notification_templates.j2 @@ -1,5 +1,7 @@ +{% if (current_notification_template_index | default(0)) == 0 %} --- controller_notifications: +{% endif %} - name: "{{ current_notification_templates_asset_value.name }}" organization: "{{ current_notification_templates_asset_value.summary_fields.organization.name }}" notification_type: "{{ current_notification_templates_asset_value.notification_type }}" @@ -19,4 +21,6 @@ controller_notifications: messages: {{ current_notification_templates_asset_value.messages | to_nice_yaml(indent=2) | indent(width=6, first=True) | replace("'{{", "!unsafe \'{{") }} {% endif %} +{% if last_notification_template | default(true) | bool %} ... +{% endif %} diff --git a/roles/filetree_create/templates/current_organizations.j2 b/roles/filetree_create/templates/current_organizations.j2 index 3836f6ced..ea103a9cc 100644 --- a/roles/filetree_create/templates/current_organizations.j2 +++ b/roles/filetree_create/templates/current_organizations.j2 @@ -1,5 +1,7 @@ +{% if (current_organization_index | default(0)) == 0 %} --- controller_organizations: +{% endif %} - name: "{{ current_organization.name }}" description: "{{ current_organization.description }}" {% if query_notification_error | length > 0 %} @@ -26,4 +28,6 @@ controller_organizations: - "{{ notification_approval.name }}" {% endfor %} {% endif %} +{% if last_organization | default(true) | bool %} ... +{% endif %} diff --git a/roles/filetree_create/templates/current_projects.j2 b/roles/filetree_create/templates/current_projects.j2 index 5e9554006..9526f3356 100644 --- a/roles/filetree_create/templates/current_projects.j2 +++ b/roles/filetree_create/templates/current_projects.j2 @@ -1,5 +1,7 @@ +{% if (current_project_index | default(0)) == 0 %} --- controller_projects: +{% endif %} - name: "{{ current_projects_asset_value.name }}" description: "{{ current_projects_asset_value.description }}" organization: "{{ current_projects_asset_value.summary_fields.organization.name | default('ToDo: The project \'' + current_projects_asset_value.name + '\' must have an organization') }}" @@ -35,4 +37,6 @@ controller_projects: - "{{ notification_success.name }}" {% endfor %} {% endif %} +{% if last_project | default(true) | bool %} ... +{% endif %} diff --git a/roles/filetree_create/templates/current_schedules.j2 b/roles/filetree_create/templates/current_schedules.j2 index 367af3851..8c7506815 100644 --- a/roles/filetree_create/templates/current_schedules.j2 +++ b/roles/filetree_create/templates/current_schedules.j2 @@ -1,5 +1,7 @@ +{% if (current_schedule_index | default(0)) == 0 %} --- controller_schedules: +{% endif %} - name: "{{ current_schedules_asset_value.name }}" {% if current_schedules_asset_value.description is defined %} description: "{{ current_schedules_asset_value.description }}" @@ -76,4 +78,6 @@ controller_schedules: {% if current_schedules_asset_value.verbosity is defined %} verbosity: {{ current_schedules_asset_value.verbosity | int }} {% endif %} +{% if last_schedule | default(true) | bool %} ... +{% endif %} diff --git a/roles/filetree_create/templates/current_team_roles.j2 b/roles/filetree_create/templates/current_team_roles.j2 index 1ba33d0c0..d70d0a080 100644 --- a/roles/filetree_create/templates/current_team_roles.j2 +++ b/roles/filetree_create/templates/current_team_roles.j2 @@ -1,4 +1,4 @@ -{% if first_team_role | bool %} +{% if first_team_role | default(true) | bool %} --- controller_roles: {% endif %} @@ -25,6 +25,6 @@ controller_roles: role: "{{ role.name | lower }}" {% endif %} {% endfor %} -{% if last_team_role | bool %} +{% if last_team_role | default(true) | bool %} ... -{%- endif -%} +{% endif %} diff --git a/roles/filetree_create/templates/current_teams.j2 b/roles/filetree_create/templates/current_teams.j2 index eafa0f076..259c47df8 100644 --- a/roles/filetree_create/templates/current_teams.j2 +++ b/roles/filetree_create/templates/current_teams.j2 @@ -1,10 +1,10 @@ -{%- if current_team_index == 0 -%} +{% if (current_team_index | default(0)) == 0 %} --- controller_teams: {% endif %} - name: "{{ current_teams_asset_value.name }}" description: "{{ current_teams_asset_value.description }}" organization: "{{ current_teams_asset_value.summary_fields.organization.name }}" -{% if last_team | bool %} +{% if last_team | default(true) | bool %} ... {% endif %} diff --git a/roles/filetree_create/templates/current_user_roles.j2 b/roles/filetree_create/templates/current_user_roles.j2 index 2a037a5a7..2170e99d6 100644 --- a/roles/filetree_create/templates/current_user_roles.j2 +++ b/roles/filetree_create/templates/current_user_roles.j2 @@ -1,5 +1,7 @@ +{% if first_user_role | default(true) | bool %} --- controller_roles: +{% endif %} {% for role in user_roles_lookvar %} {% if role.summary_fields.resource_type is defined %} - user: "{{ username }}" @@ -23,4 +25,6 @@ controller_roles: role: "{{ role.name | lower }}" {% endif %} {% endfor %} +{% if last_user_role | default(true) | bool %} ... +{% endif %} diff --git a/roles/filetree_create/templates/current_users.j2 b/roles/filetree_create/templates/current_users.j2 index fe98ce709..59f766c2f 100644 --- a/roles/filetree_create/templates/current_users.j2 +++ b/roles/filetree_create/templates/current_users.j2 @@ -1,5 +1,7 @@ +{% if (current_user_index | default(0)) == 0 %} --- controller_user_accounts: +{% endif %} - username: "{{ current_users_asset_value.username }}" password: "INITIAL" email: "{{ current_users_asset_value.email }}" @@ -8,4 +10,6 @@ controller_user_accounts: auditor: "{{ current_users_asset_value.is_system_auditor }}" superuser: "{{ current_users_asset_value.is_superuser }}" update_secrets: false +{% if last_user | default(true) | bool %} ... +{% endif %} diff --git a/roles/filetree_create/templates/current_workflow_job_templates.j2 b/roles/filetree_create/templates/current_workflow_job_templates.j2 index 90fdb512f..6800a4215 100644 --- a/roles/filetree_create/templates/current_workflow_job_templates.j2 +++ b/roles/filetree_create/templates/current_workflow_job_templates.j2 @@ -1,5 +1,7 @@ +{% if (current_workflow_job_template_index | default(0)) == 0 %} --- controller_workflows: +{% endif %} - name: "{{ current_workflow_job_templates_asset_value.name }}" description: "{{ current_workflow_job_templates_asset_value.description }}" organization: "{{ current_workflow_job_templates_asset_value.summary_fields.organization.name | default('ToDo: The WF \'' + current_workflow_job_templates_asset_value.name + '\' must belong to an organization') }}" @@ -36,12 +38,11 @@ controller_workflows: {% endfor %} {% endif %} {% endfor %} - survey_enabled: "{{ current_workflow_job_templates_asset_value.survey_enabled }}" ask_variables_on_launch: "{{ current_workflow_job_templates_asset_value.ask_variables_on_launch }}" allow_simultaneous: "{{ current_workflow_job_templates_asset_value.allow_simultaneous }}" scm_branch: "{{ current_workflow_job_templates_asset_value.scm_branch }}" webhook_service: "{{ current_workflow_job_templates_asset_value.webhook_service }}" -{% if current_workflow_job_templates_asset_value.extra_vars and current_workflow_job_templates_asset_value.extra_vars != '---' and current_workflow_job_templates_asset_value.extra_vars != '' %} +{% if current_workflow_job_templates_asset_value.extra_vars and current_workflow_job_templates_asset_value.extra_vars | length > 3 %} extra_vars: {{ current_workflow_job_templates_asset_value.extra_vars | from_yaml | to_nice_yaml(indent=2) | indent(width=6, first=False) | replace("'{{", "!unsafe \'{{") }} {%- endif %} @@ -76,5 +77,14 @@ controller_workflows: {% endfor %} {% endif %} survey_enabled: {{ current_workflow_job_templates_asset_value.survey_enabled }} - survey_spec: {{ query(controller_api_plugin, current_workflow_job_templates_asset_value.related.survey_spec, host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs)[0] }} +{% set survey_spec_contents = query(controller_api_plugin, current_workflow_job_templates_asset_value.related.survey_spec, + host=controller_hostname, oauth_token=controller_oauthtoken, verify_ssl=controller_validate_certs)[0] | + from_yaml | to_nice_yaml(indent=2,width=500) | regex_replace("\n\n[ ]*", "\\\\n") | indent(width=6, first=False) | replace("'{{", "!unsafe \'{{") | replace("^$", "") +-%} +{% if current_workflow_job_templates_asset_value.related.survey_spec is defined and survey_spec_contents | length > 3 %} + survey_spec: + {{ survey_spec_contents }} +{% endif %} +{% if last_workflow_job_template | default(true) | bool %} ... +{% endif %}