--- # Install Ansible Automation Platform via OpenShift OLM operator. # # Deploys the AAP operator, then creates a single AnsibleAutomationPlatform # CR that manages Controller, Hub, and EDA as a unified platform. # All tasks are idempotent (kubernetes.core.k8s state: present). # ------------------------------------------------------------------ # Step 1: Install AAP operator via OLM # ------------------------------------------------------------------ - name: Create AAP namespace kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: Namespace metadata: name: "{{ aap_operator_namespace }}" - name: Read global pull secret kubernetes.core.k8s_info: api_version: v1 kind: Secret namespace: openshift-config name: pull-secret register: __aap_operator_global_pull_secret - name: Copy pull secret to AAP namespace kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: Secret metadata: name: redhat-operators-pull-secret namespace: "{{ aap_operator_namespace }}" type: kubernetes.io/dockerconfigjson data: .dockerconfigjson: "{{ __aap_operator_global_pull_secret.resources[0].data['.dockerconfigjson'] }}" no_log: false - name: Create OperatorGroup for AAP kubernetes.core.k8s: state: present definition: apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: name: "{{ aap_operator_name }}" namespace: "{{ aap_operator_namespace }}" spec: targetNamespaces: - "{{ aap_operator_namespace }}" upgradeStrategy: Default - name: Subscribe to AAP operator kubernetes.core.k8s: state: present definition: apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: "{{ aap_operator_name }}" namespace: "{{ aap_operator_namespace }}" spec: channel: "{{ aap_operator_channel }}" installPlanApproval: Automatic name: "{{ aap_operator_name }}" source: "{{ aap_operator_source }}" sourceNamespace: openshift-marketplace # ------------------------------------------------------------------ # Step 2: Wait for operator to be ready # ------------------------------------------------------------------ - name: Wait for AnsibleAutomationPlatform CRD to be available kubernetes.core.k8s_info: api_version: apiextensions.k8s.io/v1 kind: CustomResourceDefinition name: ansibleautomationplatforms.aap.ansible.com register: __aap_operator_crd until: __aap_operator_crd.resources | length > 0 retries: "{{ __aap_operator_wait_retries }}" delay: 10 - name: Wait for AAP operator deployments to be ready kubernetes.core.k8s_info: api_version: apps/v1 kind: Deployment namespace: "{{ aap_operator_namespace }}" label_selectors: - "operators.coreos.com/{{ aap_operator_name }}.{{ aap_operator_namespace }}" register: __aap_operator_deploy until: >- __aap_operator_deploy.resources | length > 0 and (__aap_operator_deploy.resources | rejectattr('status.readyReplicas', 'undefined') | selectattr('status.readyReplicas', '>=', 1) | list | length) == (__aap_operator_deploy.resources | length) retries: "{{ __aap_operator_wait_retries }}" delay: 10 # ------------------------------------------------------------------ # Step 3: Deploy the unified AnsibleAutomationPlatform # ------------------------------------------------------------------ - name: Create AnsibleAutomationPlatform kubernetes.core.k8s: state: present definition: apiVersion: aap.ansible.com/v1alpha1 kind: AnsibleAutomationPlatform metadata: name: "{{ aap_operator_platform_name }}" namespace: "{{ aap_operator_namespace }}" spec: admin_user: "{{ aap_operator_admin_user }}" # PostgreSQL storage for all components (RWO) database: postgres_storage_class: "{{ aap_operator_storage_class }}" # Gateway is the primary UI/API entry point in AAP 2.5+ gateway: route_host: "{{ aap_operator_gateway_route_host | default(omit) }}" # Component toggles and per-component config controller: disabled: "{{ aap_operator_controller_disabled | bool }}" route_host: "{{ aap_operator_controller_route_host | default(omit) }}" hub: disabled: "{{ aap_operator_hub_disabled | bool }}" # Hub file/artifact storage (RWX) — must be under hub: storage_type: file file_storage_storage_class: "{{ aap_operator_hub_file_storage_class }}" file_storage_size: "{{ aap_operator_hub_file_storage_size }}" eda: disabled: "{{ aap_operator_eda_disabled | bool }}" # ------------------------------------------------------------------ # Step 3a: Clear controller route_host if not explicitly set # strategic-merge-patch (state: present) does not remove existing fields, # so we must explicitly remove /spec/controller/route_host if the user # hasn't set aap_operator_controller_route_host (e.g. after switching to # gateway-based routing). # ------------------------------------------------------------------ # The platform operator propagates route_host to the child AutomationController CR. # Both must be cleared or the controller operator will continue to set the old hostname. - name: Remove controller route_host from platform CR (use auto-generated route) kubernetes.core.k8s_json_patch: api_version: aap.ansible.com/v1alpha1 kind: AnsibleAutomationPlatform namespace: "{{ aap_operator_namespace }}" name: "{{ aap_operator_platform_name }}" patch: - op: remove path: /spec/controller/route_host when: aap_operator_controller_route_host is not defined failed_when: false # no-op if field doesn't exist - name: Remove controller route_host from child AutomationController CR kubernetes.core.k8s_json_patch: api_version: automationcontroller.ansible.com/v1beta1 kind: AutomationController namespace: "{{ aap_operator_namespace }}" name: "{{ aap_operator_platform_name }}-controller" patch: - op: remove path: /spec/route_host when: aap_operator_controller_route_host is not defined failed_when: false # no-op if field doesn't exist or CR not yet created - name: Delete aap-controller Route so operator recreates with correct hostname kubernetes.core.k8s: api_version: route.openshift.io/v1 kind: Route namespace: "{{ aap_operator_namespace }}" name: "{{ aap_operator_platform_name }}-controller" state: absent when: aap_operator_controller_route_host is not defined # ------------------------------------------------------------------ # Step 4: Wait for platform to be ready # ------------------------------------------------------------------ - name: Wait for AnsibleAutomationPlatform to be ready kubernetes.core.k8s_info: api_version: aap.ansible.com/v1alpha1 kind: AnsibleAutomationPlatform namespace: "{{ aap_operator_namespace }}" name: "{{ aap_operator_platform_name }}" register: __aap_operator_platform_status ignore_errors: true until: >- __aap_operator_platform_status.resources is defined and __aap_operator_platform_status.resources | length > 0 and (__aap_operator_platform_status.resources[0].status.conditions | default([]) | selectattr('type', '==', 'Running') | selectattr('status', '==', 'True') | list | length > 0) retries: "{{ __aap_operator_wait_retries }}" delay: 10 # ------------------------------------------------------------------ # Step 5: Display summary # ------------------------------------------------------------------ - name: Display AAP deployment summary ansible.builtin.debug: msg: - "Ansible Automation Platform deployment complete!" - " Namespace : {{ aap_operator_namespace }}" - " Platform CR: {{ aap_operator_platform_name }}" - " Controller : {{ 'disabled' if aap_operator_controller_disabled else 'enabled' }}" - " Hub : {{ 'disabled' if aap_operator_hub_disabled else 'enabled' }}" - " EDA : {{ 'disabled' if aap_operator_eda_disabled else 'enabled' }}" - "" - "Admin password secret: {{ aap_operator_platform_name }}-admin-password" - "Retrieve with: oc get secret {{ aap_operator_platform_name }}-admin-password -n {{ aap_operator_namespace }} -o jsonpath='{.data.password}' | base64 -d"