main.yml

This is where all magic happens, all steps:
rhaap base config:
- checkout rhaap base configuration
- create organization - create organization admin - create LDAP mappings - add hub credentials to organization
- push changes and start merge
- wait for the pipeline to finish
organization config:
- create repository
- clone empty repository
- create branches
- create directories/files
- add pipeline
- protect branches
- push and merge
- wait for the pipeline to finish
- add the organization to recovery

There are some very complex tasks in this playbook, know your syntax well when changing!

---
# Complete rewrite for 2.6 wth external vault  (Openbao/HashiCorp)
#
- name: Add Org_admin to AAP platform
  hosts: localhost
  gather_facts: true

  pre_tasks:
    - name: Get vars
      ansible.builtin.include_vars: env_vars.yml
      no_log: true

  tasks:
    # Add the organization namespace to vault
    - name: Create namespace (organization_short_name) for each environment
      ansible.builtin.include_tasks:
        file: vault_create_namespace.yml
      vars:
        main_ns_name: "{{ venv.key }}"
        sub_ns_name: "{{ organization_short_name | lower }}"
      loop: "{{ aap_env | dict2items }}"
      loop_control:
        loop_var: venv

    - name: Add the rhaap_admin (CaC_admin_ORG) in namespaces
      ansible.builtin.include_tasks:
        file: vault_create_secret.yml
      vars:
        secret_name: rhaap_admin
        main_ns_name: "{{ wenv.key }}"
        sub_ns_name: "{{ organization_short_name | lower }}"
        org_admin_user: "CaC_admin_{{ organization_short_name | upper }}"
        rhaap_hostname: "{{ aap_env[main_ns_name]['rhaap_hostname'] }}"
      loop: "{{ aap_env | dict2items }}"
      loop_control:
        loop_var: wenv

    - name: Add the user to base_users in all namespaces/base
      ansible.builtin.include_tasks:
        file: vault_add_key_to_base_users.yml
      vars:
        main_ns_name: "{{ senv.key }}"
        sub_ns_name: base
        new_key: "CaC_admin_{{ organization_short_name | upper }}"
        new_value: "{{ team_password }}"
      loop: "{{ aap_env | dict2items }}"
      loop_control:
        loop_var: senv

    # Start rhaap configuration
    # clone the rhaap_base repository and add things for the new organization
    - name: GitLab Post | Obtain Access Token
      ansible.builtin.include_tasks:
        file: get_gitlab_api_token.yml

    - name: Clone the GitLab repository    # noqa: command-instead-of-module
      ansible.builtin.shell: |
        git config --global user.name "{{ gitlab_user_username }}"
        git config --global user.email "{{ gitlab_user_username }}@homelab.wf"
        git config --global http.sslVerify "false"
        git clone "{{ gitlab_protocol }}oauth:{{ token }}@{{ gitlab_url }}{{ gitlab_group }}/{{ cac_project_name }}.git"
      args:
        chdir: /tmp
      changed_when: true
      no_log: false

    - name: Create the Organization
      ansible.builtin.blockinfile:
        path: "/tmp/{{ cac_project_name }}/group_vars/all/aap_organizations.yml"
        insertbefore: ...
        marker: "# {mark} ANSIBLE MANAGED BLOCK {{ organization_long_name | upper }}"
        marker_begin: "# BEGIN BLOCK {{ organization_long_name | upper }}"
        marker_end: "# END BLOCK {{ organization_long_name | upper }}"
        block: |
          {% filter indent(width=2, first=true) %}
          - name: {{ organization_long_name | upper }}
            description: Organization for team {{ organization_short_name | upper }}
          {% endfilter %}

    - name: Make the user ORG_ADMIN
      ansible.builtin.blockinfile:
        path: "/tmp/{{ cac_project_name }}/group_vars/all/gateway_role_user_assignments.yml"
        insertbefore: ...
        marker: "# {mark} ANSIBLE MANAGED BLOCK {{ organization_long_name | upper }}"
        marker_begin: "# BEGIN BLOCK {{ organization_long_name | upper }}"
        marker_end: "# END BLOCK {{ organization_long_name | upper }}"
        block: |
          {% filter indent(width=2, first=true) %}
          - role_definition: Organization Admin
            user: CaC_admin_{{ organization_short_name | upper }}
            object_ids: {{ organization_long_name | upper }}
          {% endfilter %}

    - name: Set ldap facts
      ansible.builtin.set_fact:
        ldap_pre: "{{ ldap | selectattr('name', 'match', ldap_name) | map(attribute='ldap_pre_str') | join() }}"
        ldap_post: "{{ ldap | selectattr('name', 'match', ldap_name) | map(attribute='ldap_post_str') | join() }}"
      when: add_ldap

    - name: "Add a block of text to the file gateway_authenticator_maps.yml"       # noqa: name[template]
      ansible.builtin.blockinfile:
        path: "/tmp/{{ cac_project_name }}/group_vars/all/gateway_authenticator_maps.yml"
        block: |
          {% filter indent(width=2, first=true) %}
          - name: {{ organization_long_name | upper }}-members
            authenticator: {{ ldap_name }}
            revoke: true
            map_type: organization
            organization: {{ organization_long_name | upper }}
            role: Organization Member
            triggers:
              groups:
                has_or:
                  - cn={{ ldap_pre }}{{ organization_short_name }}-a{{ ldap_post }}
                  - cn={{ ldap_pre }}{{ organization_short_name }}-d{{ ldap_post }}
                  - cn={{ ldap_pre }}{{ organization_short_name }}-o{{ ldap_post }}

          - name: {{ organization_long_name | upper }}-admins
            authenticator: {{ ldap_name }}
            revoke: true
            map_type: organization
            organization: {{ organization_long_name | upper }}
            role: Organization Admin
            triggers:
              groups:
                has_and:
                  - cn={{ ldap_pre }}{{ organization_short_name }}-a{{ ldap_post }}

          - name: {{ organization_long_name | upper }}-admin-team
            authenticator: {{ ldap_name }}
            revoke: true
            map_type: role
            organization: {{ organization_long_name | upper }}
            team: LDAP_{{ organization_short_name | upper }}_Admins
            role: Team Member
            triggers:
              groups:
                has_and:
                  - cn={{ ldap_pre }}{{ organization_short_name }}-a{{ ldap_post }}

          - name: {{ organization_long_name | upper }}-developers
            authenticator: {{ ldap_name }}
            revoke: true
            map_type: role
            organization: {{ organization_long_name | upper }}
            team: LDAP_{{ organization_short_name | upper }}_Developers
            role: Team Member
            triggers:
              groups:
                has_and:
                  - cn={{ ldap_pre }}{{ organization_short_name }}-d{{ ldap_post }}

          - name: {{ organization_long_name | upper }}-operators
            authenticator: {{ ldap_name }}
            revoke: true
            map_type: role
            organization: {{ organization_long_name | upper }}
            team: LDAP_{{ organization_short_name | upper }}_Operators
            role: Team Member
            triggers:
              groups:
                has_and:
                  - cn={{ ldap_pre }}{{ organization_short_name }}-o{{ ldap_post }}
          {% endfilter %}
        marker: "# {mark} ANSIBLE MANAGED BLOCK {{ organization_short_name | upper }} TEAM_MAP"
        marker_begin: "# BEGIN ANSIBLE MANAGED BLOCK {{ organization_short_name | upper }}"
        marker_end: "# END ANSIBLE MANAGED BLOCK {{ organization_short_name | upper }}"
        backup: false
        insertbefore: ...
      when: add_ldap

    - name: "Add a block of text to the file aap_teams.yml"       # noqa: name[template]
      ansible.builtin.blockinfile:
        path: "/tmp/{{ cac_project_name }}/group_vars/all/aap_teams.yml"
        block: |
          {% filter indent(width=2, first=true) %}
          - name: LDAP_{{ organization_short_name | upper }}_Admins
            organization: {{ organization_long_name | upper }}
            description: Organization Admins (LDAP)
          - name: LDAP_{{ organization_short_name | upper }}_Developers
            organization: {{ organization_long_name | upper }}
            description: Organization Developers (LDAP)
          - name: LDAP_{{ organization_short_name | upper }}_Operators
            organization: {{ organization_long_name | upper }}
            description: Organization Operators (LDAP)
          {% endfilter %}
        marker: "# {mark} ANSIBLE MANAGED BLOCK {{ organization_short_name | upper }} ORGANIZATION_MAP"
        marker_begin: "# BEGIN ANSIBLE MANAGED BLOCK {{ organization_short_name | upper }}"
        marker_end: "# END ANSIBLE MANAGED BLOCK {{ organization_short_name | upper }}"
        backup: false
        insertbefore: ...
      when: add_ldap

    # End gateway configuration, we now need to push the updates and run the pipeline
    # for the development environment.

    # Lets add things to the controller base configuration, before we create the config as code repository
    # for the new team/organization

    - name: "Add a block of text to the file controller_organizations.yml"       # noqa: name[template]
      ansible.builtin.blockinfile:
        path: "/tmp/{{ cac_project_name }}/group_vars/all/controller_organizations.yml"
        block: |
          {% filter indent(width=2, first=true) %}
          - name: {{ organization_long_name | upper }}
            galaxy_credentials:
              - MGT_automation_hub_token_community
              - MGT_automation_hub_token_rh_certified
              - MGT_automation_hub_token_published
              - MGT_automation_hub_token_validated
          {% endfilter %}
        marker: "# {mark} ANSIBLE MANAGED BLOCK {{ organization_short_name | upper }} ORGANIZATION_CREDS"
        marker_begin: "# BEGIN ANSIBLE MANAGED BLOCK {{ organization_short_name | upper }}"
        marker_end: "# END ANSIBLE MANAGED BLOCK {{ organization_short_name | upper }}"
        backup: false
        insertbefore: ...

    - name: "Add the organization to shared credentials in controller_roles.yml"       # noqa: name[template]
      ansible.builtin.lineinfile:
        path: "/tmp/{{ cac_project_name }}/group_vars/all/controller_roles.yml"
        line: "      - {{ organization_long_name | upper }}"
        backup: false
        firstmatch: true
        insertafter: "^  - organizations:"

    - name: "Add the new teams to shared inventory in controller_roles.yml"       # noqa: name[template]
      ansible.builtin.blockinfile:
        path: "/tmp/{{ cac_project_name }}/group_vars/all/controller_roles.yml"
        block: |
          {% filter indent(width=2, first=true) %}
              - LDAP_{{ organization_short_name | upper }}_Admins
              - LDAP_{{ organization_short_name | upper }}_Developers
          {% endfilter %}
        backup: false
        insertafter: "^    teams:"

    # End of controller base configuration for team addition
    # Now run the pipeline for the development environment.

    - name: Push the updated GitLab repository    # noqa: command-instead-of-module
      ansible.builtin.shell: |
        git config --global user.name "{{ gitlab_user_username }}"
        git config --global user.email "{{ gitlab_user_username }}@homelab.wf"
        git add --all
        git commit -m "Organization branch addition for {{ organization_long_name | upper }}"
        git push origin "{{ gitlab_default_branch }}"
      args:
        chdir: "/tmp/{{ cac_project_name }}"
      changed_when: false
      no_log: false

    - name: Delete the tempory directory
      ansible.builtin.file:
        path: /tmp/{{ cac_project_name }}
        state: absent

    - name: Wait for 10 secs
      ansible.builtin.pause:
        seconds: 10

    - name: GitLab Post | Obtain Access Token
      ansible.builtin.include_tasks:
        file: get_gitlab_api_token.yml

    - name: Create correct url for gitlab_group
      ansible.builtin.set_fact:
        gitlab_group_safe: "{{ gitlab_group | replace('/', '%2F') }}"

    - name: Check the pipeline until it has run
      ansible.builtin.uri:
        url: "{{ gitlab_protocol }}{{ gitlab_url }}api/v4/projects/{{ gitlab_group_safe }}%2F{{ cac_project_name }}/jobs"
        validate_certs: false
        headers:
          Authorization: "Bearer {{ token }}"
      register: _jobs_list
      failed_when: _jobs_list.json[0].pipeline.status == "failed"
      until: (_jobs_list.json[0].pipeline.status == "success") or (_jobs_list.json[0].pipeline.status == "failed")
      retries: 20
      delay: 20

    # Rhaap base configuration complete

    # Now start creating the team controlled config as code repository

    - name: Create GitLab Project in group
      community.general.gitlab_project:
        api_url: "{{ gitlab_protocol }}{{ gitlab_url }}"
        validate_certs: "{{ gitlab_validate_certs }}"
        api_username: "{{ gitlab_user_username }}"
        api_password: "{{ gitlab_user_password }}"
        name: "{{ team_project_name }}"
        group: "{{ gitlab_group }}"
        default_branch: "{{ gitlab_default_branch }}"
        shared_runners_enabled: true
        only_allow_merge_if_pipeline_succeeds: true
        ci_config_path: "{{ gitlab_cac_pipeline }}"
        squash_option: never
        initialize_with_readme: true
        state: present

    - name: Create the environment branches on repository
      community.general.gitlab_branch:
        api_url: "{{ gitlab_protocol }}{{ gitlab_url }}"
        validate_certs: "{{ gitlab_validate_certs }}"
        api_username: "{{ gitlab_user_username }}"
        api_password: "{{ gitlab_user_password }}"
        project: "{{ gitlab_group }}/{{ team_project_name }}"
        branch: "{{ curr_env }}"
        ref_branch: "{{ gitlab_default_branch }}"
        state: present
      vars:
        curr_env: "{{ cenv.key }}"
      loop: "{{ aap_env | dict2items }}"
      loop_control:
        loop_var: cenv

    - name: Set vault_secret CI/CD variables
      community.general.gitlab_project_variable:
        api_url: "{{ gitlab_protocol }}{{ gitlab_url }}"
        validate_certs: "{{ gitlab_verify_ssl }}"
        api_username: "{{ gitlab_user_username }}"
        api_password: "{{ gitlab_user_password }}"
        project: "{{ gitlab_group }}/{{ team_project_name }}"
        purge: false
        variables:
          - name: ORG_NAME
            value: "{{ organization_short_name | lower }}"
            masked: false
            protected: true
            environment_scope: '*'

    - name: Clone the new gitlab repository  # noqa: command-instead-of-module
      ansible.builtin.shell: |
        git config --global user.name "{{ gitlab_user_username }}"
        git config --global user.email "{{ gitlab_user_username }}@homelab.wf"
        git config --global http.sslVerify "false"
        git clone "{{ gitlab_protocol }}oauth:{{ token }}@{{ gitlab_url }}{{ gitlab_group }}/{{ team_project_name }}.git"
      args:
        chdir: /tmp
      changed_when: true
      no_log: true

    - name: Get other vars
      ansible.builtin.include_vars:
        file: other_vars.yml

    - name: Checkout the branch to push     # noqa: command-instead-of-module
      ansible.builtin.shell: |
        git config --global user.name "{{ gitlab_user_username }}"
        git config --global user.email "{{ gitlab_user_username }}@homelab.wf"
        git config --global http.sslVerify "false"
        git checkout -b initial
      args:
        chdir: "/tmp/{{ team_project_name }}"
      changed_when: true

    - name: Create the list with envs
      ansible.builtin.set_fact:
        env_list: |-
          [
          {%- for env in code_environment_vars -%}
            '{{ env }}'
          {%- if not loop.last -%},{%- endif -%}
          {%- endfor -%}
          ]

    - name: Create group_var directories
      ansible.builtin.file:
        path: "/tmp/{{ team_project_name }}/group_vars/{{ curr_env }}"
        state: directory
        mode: '0755'
      loop: "{{ env_list }}"
      loop_control:
        loop_var: curr_env

    - name: Create host_var directories
      ansible.builtin.file:
        path: "/tmp/{{ team_project_name }}/host_vars/aap_{{ curr_env }}"
        state: directory
        mode: '0755'
      loop: "{{ env_list }}"
      loop_control:
        loop_var: curr_env
      when: curr_env != 'all'

    - name: Template the pipeline inventory
      ansible.builtin.template:
        src: repo_inventory.yaml.j2
        dest: "/tmp/{{ team_project_name }}/inventory.yaml"
        mode: "0644"

    - name: Place the README.md
      ansible.builtin.copy:
        src: README.md
        dest: "/tmp/{{ team_project_name }}/README.md"
        mode: "0644"

    - name: Template the aap_env.yml
      ansible.builtin.template:
        src: aap_env.yml.j2
        dest: "/tmp/{{ team_project_name }}/host_vars/aap_{{ curr_env1 }}/aap_{{ curr_env1 }}.yaml"
        mode: "0644"
      loop: "{{ env_list }}"
      loop_control:
        loop_var: curr_env1
      when: curr_env1 != 'all'

    - name: Copy the main.yml playbook
      ansible.builtin.copy:
        src: main.yml.txt
        dest: "/tmp/{{ team_project_name }}/main.yml"
        mode: "0644"

    - name: Create the list of templates
      ansible.builtin.set_fact:
        template_files:
          - controller_credential_input_sources
          - controller_credentials
          - controller_hosts
          - controller_inventories
          - controller_inventory_sources
          - controller_labels
          - controller_notifications
          - controller_projects
          - controller_roles
          - controller_schedules
          - controller_templates
          - controller_workflows

    - name: Create the loop var
      ansible.builtin.set_fact:
        template_loop: |-
          [
          {%- for env in code_environment_vars -%}
            {%- for file in template_files -%}
             '{{ env }},{{ file }}'
          {%- if not loop.last -%},
          {%- endif -%}
          {%- endfor -%}
          {%- if not loop.last -%},
          {%- endif -%}
          {%- endfor -%}
          ]

    - name: "Template files loop"
      ansible.builtin.template:
        src: "{{ curr_file.split(',')[-1] }}.yml.j2"
        dest: "/tmp/{{ team_project_name }}/group_vars/{{ curr_file.split(',')[0] }}/{{ curr_file.split(',')[-1] }}.yml"
        lstrip_blocks: true
        mode: "0640"
      loop: "{{ template_loop }}"
      loop_control:
        loop_var: curr_file

    - name: Remove obsolete empty lines from controller_credentials.yml
      ansible.builtin.replace:
        path: "/tmp/{{ team_project_name }}/group_vars/{{ curr_env2 }}/controller_credentials.yml"
        after: '      username:'
        regexp: '(^\s*$)'
        replace: ''
      loop: "{{ env_list }}"
      loop_control:
        loop_var: curr_env2

    - name: Push the updated GitLab repository and create merge request  # noqa: command-instead-of-module
      ansible.builtin.shell: |
        git add --all
        git commit -m 'initial config'
        git push origin initial -o merge_request.create -o merge_request.target="{{ gitlab_default_branch }}" -o merge_request.merge_when_pipeline_succeeds
      args:
        chdir: "/tmp/{{ team_project_name }}"
      changed_when: false

    - name: Delete the tempory directory
      ansible.builtin.file:
        path: /tmp/{{ team_project_name }}
        state: absent

    - name: Protected branch block
      block:

        - name: Protect created branches
          community.general.gitlab_protected_branch:
            api_url: "{{ gitlab_protocol }}{{ gitlab_url }}"
            validate_certs: "{{ gitlab_validate_certs }}"
            api_username: "{{ gitlab_user_username }}"
            api_password: "{{ gitlab_user_password }}"
            project: "{{ gitlab_group }}/{{ team_project_name }}"
            name: "{{ benv.key }}"
            merge_access_levels: maintainer
            push_access_level: maintainer
          no_log: true
          loop: "{{ aap_env | dict2items }}"
          loop_control:
            loop_var: benv

      rescue:

        - name: Print only in case of protection error
          ansible.builtin.debug:
            msg:
              - "The branches for the repository were not protected, due to an error."
              - "The error is that the account used to create the repository is not "
              - "the owner of the repository."
              - "Please set the protection manually...."

        - name: Fail the playbook due to error.
          ansible.builtin.fail:
            msg: "Creation was succesfull, only the branch protection was not set, see message above"

    - name: GitLab Post | Obtain Access Token
      ansible.builtin.include_tasks:
        file: get_gitlab_api_token.yml

    - name: Check the pipeline until it has run
      ansible.builtin.uri:
        url: "{{ gitlab_protocol }}{{ gitlab_url }}api/v4/projects/{{ gitlab_group_safe }}%2F{{ team_project_name }}/jobs"
        validate_certs: "{{ gitlab_validate_certs }}"
        headers:
          Authorization: "Bearer {{ token }}"
      register: _jobs_list
      failed_when: _jobs_list.json[0].pipeline.status == "failed"
      until: (_jobs_list.json[0].pipeline.status == "success") or (_jobs_list.json[0].pipeline.status == "failed")
      retries: 30
      delay: 15

    # Add the new organization repository to the recovery process for both environments
    # you could create a loop for this
    - name: Clone the Recovery DEV Branch gitlab repository
      ansible.builtin.git:
        repo: "https://{{ gitlab_user_username }}:{{ gitlab_user_password }}@{{ gitlab_url }}/cac_26/recover_rhaap.git"
        dest: "/tmp/recover_rhaap"
        version: dev
        clone: true
        update: true

    - name: Add new EE to Recovery DEV Branch env_vars
      ansible.builtin.lineinfile:
        path: "/tmp/recover_rhaap/env_vars.yml"
        line: "  - {{ gitlab_group }}/{{ team_project_name }}"
        insertafter: "  - cac_26/rhaap_cac_"

    - name: Push the new env_vars to Recovery DEV Branch GIT              # noqa: command-instead-of-module
      ansible.builtin.shell: |
        git config --global user.name "{{ gitlab_user_username }}"
        git config --global user.email "{{ gitlab_user_username }}@homelab"
        git add --all
        git commit -m 'initial config'
        git push origin dev
      args:
        chdir: "/tmp/recover_rhaap"
      changed_when: false

    - name: Delete the tempory recovery DEV directory
      ansible.builtin.file:
        path: "/tmp/recovery_rhaap"
        state: absent

    - name: Clone the Recovery MAIN Branch gitlab repository
      ansible.builtin.git:
        repo: "https://{{ gitlab_user_username }}:{{ gitlab_user_password }}@{{ gitlab_url }}/cac_26/recover_rhaap.git"
        dest: "/tmp/recover_rhaap"
        version: master
        clone: true
        update: true

    - name: Add new EE to Recovery MAIN Branch env_vars
      ansible.builtin.lineinfile:
        path: "/tmp/recover_rhaap/env_vars.yml"
        line: "  - {{ gitlab_group }}/{{ team_project_name }}"
        insertafter: "  - cac_26/rhaap_cac_"

    - name: Push the new env_vars to MAIN Branch GIT              # noqa: command-instead-of-module
      ansible.builtin.shell: |
        git config --global user.name "{{ gitlab_user_username }}"
        git config --global user.email "{{ gitlab_user_username }}@homelab"
        git add --all
        git commit -m 'initial config'
        git push origin master
      args:
        chdir: "/tmp/recover_rhaap"
      changed_when: false

    - name: Delete the tempory recovery MAIN directory
      ansible.builtin.file:
        path: "/tmp/recovery_rhaap"
        state: absent

Back