272 lines
13 KiB
YAML
272 lines
13 KiB
YAML
---
|
|
# Install Automation Orchestrator via its OpenShift OLM operator.
|
|
#
|
|
# Automation Orchestrator is bring-your-own-PostgreSQL: this role only creates the
|
|
# OperatorGroup/Subscription and the AutomationOrchestrator CR — it references
|
|
# existing K8s Secrets (keys: database/username/password, or host/port/database/
|
|
# username/password for CNPG's basic-auth secrets) rather than creating them.
|
|
# Pair with the cloudnativepg_operator role (defaults match its secret names) or
|
|
# point postgres_* variables at a customer-managed PostgreSQL instance.
|
|
#
|
|
# Modeled on https://github.com/ansible/aapctl (internal/install/automationorchestrator)
|
|
# and https://github.com/automation-nexus/automation-orchestrator-operator.
|
|
# With Manual install-plan approval (the default) this role approves the initial
|
|
# InstallPlan itself; later upgrade InstallPlans are left for manual approval.
|
|
#
|
|
# All tasks are idempotent (kubernetes.core.k8s state: present).
|
|
|
|
- name: Verify PostgreSQL host is set
|
|
ansible.builtin.assert:
|
|
that:
|
|
- automation_orchestrator_operator_postgres_host | length > 0
|
|
fail_msg: >-
|
|
automation_orchestrator_operator_postgres_host must be set. Automation Orchestrator is
|
|
bring-your-own-PostgreSQL — either run the cloudnativepg_operator role first (its defaults
|
|
match this role's) or point this at a customer-managed PostgreSQL instance.
|
|
|
|
# ------------------------------------------------------------------
|
|
# Step 0: Mirror pre-release AAP 2.7 images (IDMS) — triggers an MCP rollout
|
|
# ------------------------------------------------------------------
|
|
- name: Configure pre-release image mirrors
|
|
ansible.builtin.include_tasks: image_mirrors.yml
|
|
when: automation_orchestrator_operator_image_digest_mirrors | length > 0
|
|
|
|
# ------------------------------------------------------------------
|
|
# Step 1: Install Automation Orchestrator operator via OLM
|
|
# ------------------------------------------------------------------
|
|
- name: Create Automation Orchestrator namespace
|
|
kubernetes.core.k8s:
|
|
state: present
|
|
definition:
|
|
apiVersion: v1
|
|
kind: Namespace
|
|
metadata:
|
|
name: "{{ automation_orchestrator_operator_operator_namespace }}"
|
|
|
|
- name: Create Automation Orchestrator app namespace
|
|
kubernetes.core.k8s:
|
|
state: present
|
|
definition:
|
|
apiVersion: v1
|
|
kind: Namespace
|
|
metadata:
|
|
name: "{{ automation_orchestrator_operator_app_namespace }}"
|
|
when: automation_orchestrator_operator_app_namespace != automation_orchestrator_operator_operator_namespace
|
|
|
|
- name: Create CatalogSource for Automation Orchestrator
|
|
kubernetes.core.k8s:
|
|
state: present
|
|
definition:
|
|
apiVersion: operators.coreos.com/v1alpha1
|
|
kind: CatalogSource
|
|
metadata:
|
|
name: "{{ automation_orchestrator_operator_catalog_source_name }}"
|
|
namespace: openshift-marketplace
|
|
spec:
|
|
sourceType: grpc
|
|
image: "{{ automation_orchestrator_operator_catalog_image }}"
|
|
displayName: Automation Orchestrator
|
|
when: automation_orchestrator_operator_catalog_image | length > 0
|
|
|
|
# OLM allows only one OperatorGroup per namespace; reuse any existing one
|
|
# (e.g. the auto-named group an OperatorHub install creates).
|
|
- name: Look up existing OperatorGroups
|
|
kubernetes.core.k8s_info:
|
|
api_version: operators.coreos.com/v1
|
|
kind: OperatorGroup
|
|
namespace: "{{ automation_orchestrator_operator_operator_namespace }}"
|
|
register: __automation_orchestrator_operator_ogs
|
|
|
|
- name: Create OperatorGroup for Automation Orchestrator
|
|
kubernetes.core.k8s:
|
|
state: present
|
|
definition:
|
|
apiVersion: operators.coreos.com/v1
|
|
kind: OperatorGroup
|
|
metadata:
|
|
name: "{{ automation_orchestrator_operator_name }}"
|
|
namespace: "{{ automation_orchestrator_operator_operator_namespace }}"
|
|
spec: {}
|
|
when: __automation_orchestrator_operator_ogs.resources | length == 0
|
|
|
|
- name: Subscribe to Automation Orchestrator operator
|
|
kubernetes.core.k8s:
|
|
state: present
|
|
definition:
|
|
apiVersion: operators.coreos.com/v1alpha1
|
|
kind: Subscription
|
|
metadata:
|
|
name: "{{ automation_orchestrator_operator_name }}"
|
|
namespace: "{{ automation_orchestrator_operator_operator_namespace }}"
|
|
spec:
|
|
channel: "{{ automation_orchestrator_operator_channel }}"
|
|
installPlanApproval: "{{ automation_orchestrator_operator_install_plan_approval }}"
|
|
name: "{{ automation_orchestrator_operator_name }}"
|
|
source: "{{ automation_orchestrator_operator_catalog_source_name }}"
|
|
sourceNamespace: openshift-marketplace
|
|
|
|
# ------------------------------------------------------------------
|
|
# Step 2: Approve the initial InstallPlan (if needed) and wait for the CSV
|
|
# ------------------------------------------------------------------
|
|
# Once a CSV is installed, pending InstallPlans are upgrades — leave those for
|
|
# manual approval rather than approving them on every run.
|
|
- name: Wait for OLM to resolve the Subscription
|
|
kubernetes.core.k8s_info:
|
|
api_version: operators.coreos.com/v1alpha1
|
|
kind: Subscription
|
|
namespace: "{{ automation_orchestrator_operator_operator_namespace }}"
|
|
name: "{{ automation_orchestrator_operator_name }}"
|
|
register: __automation_orchestrator_operator_sub
|
|
until: >-
|
|
__automation_orchestrator_operator_sub.resources | length > 0 and
|
|
((__automation_orchestrator_operator_sub.resources[0].status.installedCSV | default('')) | length > 0 or
|
|
(__automation_orchestrator_operator_sub.resources[0].status.installPlanRef.name | default('')) | length > 0)
|
|
retries: "{{ __automation_orchestrator_operator_wait_retries }}"
|
|
delay: 10
|
|
|
|
- name: Resolve installed CSV name
|
|
ansible.builtin.set_fact:
|
|
__automation_orchestrator_operator_csv_name: >-
|
|
{{ __automation_orchestrator_operator_sub.resources[0].status.installedCSV | default('') }}
|
|
|
|
- name: Approve the initial InstallPlan
|
|
when: __automation_orchestrator_operator_csv_name | length == 0
|
|
block:
|
|
- name: Read the InstallPlan
|
|
kubernetes.core.k8s_info:
|
|
api_version: operators.coreos.com/v1alpha1
|
|
kind: InstallPlan
|
|
namespace: "{{ automation_orchestrator_operator_operator_namespace }}"
|
|
name: "{{ __automation_orchestrator_operator_sub.resources[0].status.installPlanRef.name }}"
|
|
register: __automation_orchestrator_operator_installplan
|
|
|
|
- name: Approve the InstallPlan
|
|
kubernetes.core.k8s_json_patch:
|
|
api_version: operators.coreos.com/v1alpha1
|
|
kind: InstallPlan
|
|
namespace: "{{ automation_orchestrator_operator_operator_namespace }}"
|
|
name: "{{ __automation_orchestrator_operator_sub.resources[0].status.installPlanRef.name }}"
|
|
patch:
|
|
- op: add
|
|
path: /spec/approved
|
|
value: true
|
|
when: not (__automation_orchestrator_operator_installplan.resources[0].spec.approved | default(false))
|
|
|
|
- name: Resolve CSV name from the InstallPlan
|
|
ansible.builtin.set_fact:
|
|
__automation_orchestrator_operator_csv_name: >-
|
|
{{ __automation_orchestrator_operator_installplan.resources[0].spec.clusterServiceVersionNames[0] }}
|
|
|
|
- name: Wait for Automation Orchestrator CSV to succeed
|
|
kubernetes.core.k8s_info:
|
|
api_version: operators.coreos.com/v1alpha1
|
|
kind: ClusterServiceVersion
|
|
namespace: "{{ automation_orchestrator_operator_operator_namespace }}"
|
|
name: "{{ __automation_orchestrator_operator_csv_name }}"
|
|
register: __automation_orchestrator_operator_csv
|
|
until: >-
|
|
__automation_orchestrator_operator_csv.resources | length > 0 and
|
|
__automation_orchestrator_operator_csv.resources[0].status.phase | default('') == 'Succeeded'
|
|
retries: "{{ __automation_orchestrator_operator_wait_retries }}"
|
|
delay: 10
|
|
|
|
- name: Wait for AutomationOrchestrator CRD to be available
|
|
kubernetes.core.k8s_info:
|
|
api_version: apiextensions.k8s.io/v1
|
|
kind: CustomResourceDefinition
|
|
name: automationorchestrators.aap.ansible.com
|
|
register: __automation_orchestrator_operator_crd
|
|
until: __automation_orchestrator_operator_crd.resources | length > 0
|
|
retries: "{{ __automation_orchestrator_operator_wait_retries }}"
|
|
delay: 10
|
|
|
|
# ------------------------------------------------------------------
|
|
# Step 3: Deploy the AutomationOrchestrator instance
|
|
# ------------------------------------------------------------------
|
|
- name: Build AutomationOrchestrator spec
|
|
ansible.builtin.set_fact:
|
|
__automation_orchestrator_operator_spec: >-
|
|
{{
|
|
{
|
|
'imagePullSecrets': automation_orchestrator_operator_image_pull_secrets,
|
|
'postgres': {
|
|
'host': automation_orchestrator_operator_postgres_host,
|
|
'port': automation_orchestrator_operator_postgres_port,
|
|
'sslMode': automation_orchestrator_operator_postgres_ssl_mode,
|
|
'backendDatabase': {'secretRef': {'name': automation_orchestrator_operator_backend_db_secret_name}},
|
|
'temporalDatabase': {'secretRef': {'name': automation_orchestrator_operator_temporal_db_secret_name}},
|
|
},
|
|
'ingress': {
|
|
'type': automation_orchestrator_operator_ingress_type,
|
|
'annotations': automation_orchestrator_operator_ingress_annotations,
|
|
},
|
|
'backend': automation_orchestrator_operator_backend,
|
|
'ui': automation_orchestrator_operator_ui,
|
|
'worker': automation_orchestrator_operator_worker,
|
|
'backgroundWorker': automation_orchestrator_operator_background_worker,
|
|
'redis': automation_orchestrator_operator_redis,
|
|
'temporal': {'server': automation_orchestrator_operator_temporal_server},
|
|
}
|
|
| combine(
|
|
{'postgres': {'caCertSecretRef': {'name': automation_orchestrator_operator_postgres_ca_cert_secret}}} if automation_orchestrator_operator_postgres_ca_cert_secret else {},
|
|
recursive=True
|
|
)
|
|
| combine(
|
|
{'ingress': {'host': automation_orchestrator_operator_ingress_host}} if automation_orchestrator_operator_ingress_host else {},
|
|
recursive=True
|
|
)
|
|
| combine(
|
|
{'ingress': {'tlsSecretRef': {'name': automation_orchestrator_operator_ingress_tls_secret_name}}}
|
|
if (automation_orchestrator_operator_ingress_type == 'Ingress' and automation_orchestrator_operator_ingress_tls_secret_name)
|
|
else {},
|
|
recursive=True
|
|
)
|
|
| combine(automation_orchestrator_operator_extra_spec, recursive=True)
|
|
}}
|
|
|
|
- name: Create AutomationOrchestrator instance
|
|
kubernetes.core.k8s:
|
|
state: present
|
|
definition:
|
|
apiVersion: aap.ansible.com/v1alpha1
|
|
kind: AutomationOrchestrator
|
|
metadata:
|
|
name: "{{ automation_orchestrator_operator_instance_name }}"
|
|
namespace: "{{ automation_orchestrator_operator_app_namespace }}"
|
|
spec: "{{ __automation_orchestrator_operator_spec }}"
|
|
|
|
# ------------------------------------------------------------------
|
|
# Step 4: Wait for the instance to be ready
|
|
# ------------------------------------------------------------------
|
|
- name: Wait for AutomationOrchestrator to be ready
|
|
kubernetes.core.k8s_info:
|
|
api_version: aap.ansible.com/v1alpha1
|
|
kind: AutomationOrchestrator
|
|
namespace: "{{ automation_orchestrator_operator_app_namespace }}"
|
|
name: "{{ automation_orchestrator_operator_instance_name }}"
|
|
register: __automation_orchestrator_operator_status
|
|
ignore_errors: true
|
|
until: >-
|
|
__automation_orchestrator_operator_status.resources is defined and
|
|
__automation_orchestrator_operator_status.resources | length > 0 and
|
|
(__automation_orchestrator_operator_status.resources[0].status.conditions | default([])
|
|
| selectattr('type', '==', 'Ready')
|
|
| selectattr('status', '==', 'True') | list | length > 0)
|
|
retries: "{{ __automation_orchestrator_operator_wait_retries }}"
|
|
delay: 10
|
|
|
|
# ------------------------------------------------------------------
|
|
# Step 5: Display summary
|
|
# ------------------------------------------------------------------
|
|
- name: Display Automation Orchestrator deployment summary
|
|
ansible.builtin.debug:
|
|
msg:
|
|
- "Automation Orchestrator deployment complete!"
|
|
- " Namespace : {{ automation_orchestrator_operator_app_namespace }}"
|
|
- " Instance : {{ automation_orchestrator_operator_instance_name }}"
|
|
- " Ingress type: {{ automation_orchestrator_operator_ingress_type }}"
|
|
- ""
|
|
- "Find the UI hostname with: oc get routes -n {{ automation_orchestrator_operator_app_namespace }}"
|
|
- "The initial admin password is auto-generated unless spec.secrets.initialAdminPasswordSecretRef is set:"
|
|
- " oc get secret {{ automation_orchestrator_operator_instance_name }}-initial-admin-password -n {{ automation_orchestrator_operator_app_namespace }} -o jsonpath='{.data.password}' | base64 -d"
|