Add Automation Orchestrator Install and setup
This commit is contained in:
50
roles/cloudnativepg_operator/defaults/main.yml
Normal file
50
roles/cloudnativepg_operator/defaults/main.yml
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
# --- OLM subscription ---
|
||||
# CloudNativePG is in the certified-operators catalog by default (no custom
|
||||
# CatalogSource needed, unlike automation_orchestrator_operator).
|
||||
cloudnativepg_operator_operator_namespace: cloudnative-pg
|
||||
cloudnativepg_operator_channel: stable-v1
|
||||
cloudnativepg_operator_name: cloudnative-pg
|
||||
cloudnativepg_operator_catalog_source: certified-operators
|
||||
cloudnativepg_operator_wait_timeout: 600
|
||||
|
||||
# --- Cluster CR ---
|
||||
# Namespace for the Cluster, credential Secrets, and Database CRs. Defaults to
|
||||
# the automation_orchestrator_operator app namespace — keep the two in sync if overridden.
|
||||
cloudnativepg_operator_cluster_namespace: automation-orchestrator
|
||||
cloudnativepg_operator_cluster_name: orchestrator-postgres
|
||||
cloudnativepg_operator_owner_user: orchestrator
|
||||
cloudnativepg_operator_instances: 1
|
||||
cloudnativepg_operator_image_name: ghcr.io/cloudnative-pg/postgresql:15
|
||||
cloudnativepg_operator_storage_size: 5Gi
|
||||
cloudnativepg_operator_storage_class: ""
|
||||
cloudnativepg_operator_max_connections: 200
|
||||
|
||||
# --- Databases (Database CRs, all owned by cloudnativepg_operator_owner_user) ---
|
||||
cloudnativepg_operator_databases:
|
||||
- name: orchestrator
|
||||
dbname: orchestrator
|
||||
- name: temporal
|
||||
dbname: temporal
|
||||
- name: temporal-visibility
|
||||
dbname: temporal_visibility
|
||||
|
||||
# --- Credential secrets (type kubernetes.io/basic-auth) ---
|
||||
# All share the same generated username/password; only the referenced database differs.
|
||||
# secrets[0] is used as the CNPG bootstrap.initdb secret (creates the owner role + first DB).
|
||||
cloudnativepg_operator_secrets:
|
||||
- name: orchestrator-postgres-secret
|
||||
database: orchestrator
|
||||
- name: temporal-postgres-secret
|
||||
database: temporal
|
||||
- name: temporal-visibility-postgres-secret
|
||||
database: temporal_visibility
|
||||
|
||||
# --- Vault ---
|
||||
# KV2 path/key where the generated postgres password is stored and retrieved.
|
||||
cloudnativepg_operator_vault_mount: kv
|
||||
cloudnativepg_operator_vault_path: cloudnativepg/orchestrator-postgres
|
||||
|
||||
# --- Debugging ---
|
||||
# Set to false to disable no_log and expose secret values in task output.
|
||||
cloudnativepg_operator_no_log: true
|
||||
89
roles/cloudnativepg_operator/meta/argument_specs.yml
Normal file
89
roles/cloudnativepg_operator/meta/argument_specs.yml
Normal file
@@ -0,0 +1,89 @@
|
||||
---
|
||||
argument_specs:
|
||||
main:
|
||||
short_description: Install CloudNativePG via OLM and provision a PostgreSQL Cluster + Databases
|
||||
description:
|
||||
- Installs the CloudNativePG operator via OLM (certified-operators catalog, Manual install-plan
|
||||
approval which this role approves itself) and creates a single-instance PostgreSQL Cluster CR
|
||||
with Database CRs for the orchestrator, temporal, and temporal_visibility databases — all owned
|
||||
by one shared PostgreSQL role.
|
||||
- >-
|
||||
WARNING: this is a demo/dev-oriented, non-HA PostgreSQL deployment. For production, point
|
||||
automation_orchestrator_operator at a customer-managed PostgreSQL instance instead.
|
||||
- The generated owner-role password is stored in Vault at cloudnativepg_operator_vault_path
|
||||
and reused on subsequent runs for idempotency.
|
||||
options:
|
||||
cloudnativepg_operator_operator_namespace:
|
||||
description: Namespace for the CloudNativePG operator.
|
||||
type: str
|
||||
default: cloudnative-pg
|
||||
cloudnativepg_operator_channel:
|
||||
description: OLM subscription channel.
|
||||
type: str
|
||||
default: stable-v1
|
||||
cloudnativepg_operator_name:
|
||||
description: Operator package name in the catalog.
|
||||
type: str
|
||||
default: cloudnative-pg
|
||||
cloudnativepg_operator_catalog_source:
|
||||
description: Name of the CatalogSource to subscribe from.
|
||||
type: str
|
||||
default: certified-operators
|
||||
cloudnativepg_operator_wait_timeout:
|
||||
description: Seconds to wait for the operator, CSV, and Database CRs to become ready.
|
||||
type: int
|
||||
default: 600
|
||||
cloudnativepg_operator_cluster_namespace:
|
||||
description: Namespace for the Cluster CR, credential Secrets, and Database CRs.
|
||||
type: str
|
||||
default: automation-orchestrator
|
||||
cloudnativepg_operator_cluster_name:
|
||||
description: Name of the CloudNativePG Cluster CR.
|
||||
type: str
|
||||
default: orchestrator-postgres
|
||||
cloudnativepg_operator_owner_user:
|
||||
description: PostgreSQL role that owns all provisioned databases.
|
||||
type: str
|
||||
default: orchestrator
|
||||
cloudnativepg_operator_instances:
|
||||
description: Number of Postgres instances in the Cluster (1 = no HA).
|
||||
type: int
|
||||
default: 1
|
||||
cloudnativepg_operator_image_name:
|
||||
description: PostgreSQL container image for the Cluster.
|
||||
type: str
|
||||
default: ghcr.io/cloudnative-pg/postgresql:15
|
||||
cloudnativepg_operator_storage_size:
|
||||
description: Size of the Cluster's PersistentVolumeClaim.
|
||||
type: str
|
||||
default: 5Gi
|
||||
cloudnativepg_operator_storage_class:
|
||||
description: StorageClass for the Cluster's PVC. Empty string uses the cluster default.
|
||||
type: str
|
||||
default: ""
|
||||
cloudnativepg_operator_max_connections:
|
||||
description: postgresql.parameters.max_connections. Set to 0 to omit and use the Postgres default.
|
||||
type: int
|
||||
default: 200
|
||||
cloudnativepg_operator_databases:
|
||||
description: List of {name, dbname} Database CRs to create, all owned by cloudnativepg_operator_owner_user.
|
||||
type: list
|
||||
elements: dict
|
||||
cloudnativepg_operator_secrets:
|
||||
description: >-
|
||||
List of {name, database} credential Secrets to create (type kubernetes.io/basic-auth), all
|
||||
sharing the same generated username/password. secrets[0] is used as the CNPG bootstrap.initdb secret.
|
||||
type: list
|
||||
elements: dict
|
||||
cloudnativepg_operator_vault_mount:
|
||||
description: Vault KV2 mount point where the generated owner-role password is stored.
|
||||
type: str
|
||||
default: kv
|
||||
cloudnativepg_operator_vault_path:
|
||||
description: Vault KV2 path where the generated owner-role password is stored.
|
||||
type: str
|
||||
default: cloudnativepg/orchestrator-postgres
|
||||
cloudnativepg_operator_no_log:
|
||||
description: Set to false to disable no_log and expose secret values in task output. Never set false in shared environments.
|
||||
type: bool
|
||||
default: true
|
||||
18
roles/cloudnativepg_operator/meta/main.yml
Normal file
18
roles/cloudnativepg_operator/meta/main.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
galaxy_info:
|
||||
author: ptoal
|
||||
description: Install CloudNativePG via OLM and provision a PostgreSQL Cluster for Automation Orchestrator
|
||||
license: MIT
|
||||
min_ansible_version: "2.16"
|
||||
platforms:
|
||||
- name: GenericLinux
|
||||
versions:
|
||||
- all
|
||||
galaxy_tags:
|
||||
- openshift
|
||||
- postgresql
|
||||
- cnpg
|
||||
- operator
|
||||
- olm
|
||||
|
||||
dependencies: []
|
||||
229
roles/cloudnativepg_operator/tasks/main.yml
Normal file
229
roles/cloudnativepg_operator/tasks/main.yml
Normal file
@@ -0,0 +1,229 @@
|
||||
---
|
||||
# Install CloudNativePG via OLM and provision the PostgreSQL Cluster + Database CRs
|
||||
# and credential Secrets that back Automation Orchestrator (backend + Temporal +
|
||||
# Temporal Visibility databases, one shared owner role).
|
||||
#
|
||||
# WARNING: this is a single-instance (no HA), operator-provisioned PostgreSQL
|
||||
# cluster intended for demo/dev use. For production, point automation_orchestrator_operator
|
||||
# at a customer-managed PostgreSQL instance instead of running this role.
|
||||
#
|
||||
# Modeled on https://github.com/ansible/aapctl (internal/install/cloudnativepg).
|
||||
# CloudNativePG's OLM subscription uses Manual install-plan approval, so this role
|
||||
# approves the InstallPlan itself rather than relying on Automatic.
|
||||
#
|
||||
# All tasks are idempotent (kubernetes.core.k8s state: present).
|
||||
|
||||
- name: Resolve postgres credentials from Vault
|
||||
ansible.builtin.include_tasks: vault_secrets.yml
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Step 1: Install CloudNativePG operator via OLM
|
||||
# ------------------------------------------------------------------
|
||||
- name: Create CloudNativePG operator namespace
|
||||
kubernetes.core.k8s:
|
||||
state: present
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ cloudnativepg_operator_operator_namespace }}"
|
||||
|
||||
- name: Create CloudNativePG OperatorGroup
|
||||
kubernetes.core.k8s:
|
||||
state: present
|
||||
definition:
|
||||
apiVersion: operators.coreos.com/v1
|
||||
kind: OperatorGroup
|
||||
metadata:
|
||||
name: "{{ cloudnativepg_operator_name }}"
|
||||
namespace: "{{ cloudnativepg_operator_operator_namespace }}"
|
||||
spec: {}
|
||||
|
||||
- name: Subscribe to CloudNativePG operator
|
||||
kubernetes.core.k8s:
|
||||
state: present
|
||||
definition:
|
||||
apiVersion: operators.coreos.com/v1alpha1
|
||||
kind: Subscription
|
||||
metadata:
|
||||
name: "{{ cloudnativepg_operator_name }}"
|
||||
namespace: "{{ cloudnativepg_operator_operator_namespace }}"
|
||||
spec:
|
||||
channel: "{{ cloudnativepg_operator_channel }}"
|
||||
installPlanApproval: Manual
|
||||
name: "{{ cloudnativepg_operator_name }}"
|
||||
source: "{{ cloudnativepg_operator_catalog_source }}"
|
||||
sourceNamespace: openshift-marketplace
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Step 2: Approve the Manual InstallPlan and wait for the CSV to succeed
|
||||
# ------------------------------------------------------------------
|
||||
- name: Wait for OLM to create an InstallPlan for the Subscription
|
||||
kubernetes.core.k8s_info:
|
||||
api_version: operators.coreos.com/v1alpha1
|
||||
kind: Subscription
|
||||
namespace: "{{ cloudnativepg_operator_operator_namespace }}"
|
||||
name: "{{ cloudnativepg_operator_name }}"
|
||||
register: __cloudnativepg_operator_sub
|
||||
until: >-
|
||||
__cloudnativepg_operator_sub.resources | length > 0 and
|
||||
(__cloudnativepg_operator_sub.resources[0].status.installPlanRef.name | default('')) | length > 0
|
||||
retries: "{{ __cloudnativepg_operator_wait_retries }}"
|
||||
delay: 10
|
||||
|
||||
- name: Read the InstallPlan
|
||||
kubernetes.core.k8s_info:
|
||||
api_version: operators.coreos.com/v1alpha1
|
||||
kind: InstallPlan
|
||||
namespace: "{{ cloudnativepg_operator_operator_namespace }}"
|
||||
name: "{{ __cloudnativepg_operator_sub.resources[0].status.installPlanRef.name }}"
|
||||
register: __cloudnativepg_operator_installplan
|
||||
|
||||
- name: Approve the InstallPlan
|
||||
kubernetes.core.k8s_json_patch:
|
||||
api_version: operators.coreos.com/v1alpha1
|
||||
kind: InstallPlan
|
||||
namespace: "{{ cloudnativepg_operator_operator_namespace }}"
|
||||
name: "{{ __cloudnativepg_operator_sub.resources[0].status.installPlanRef.name }}"
|
||||
patch:
|
||||
- op: add
|
||||
path: /spec/approved
|
||||
value: true
|
||||
|
||||
- name: Wait for CloudNativePG CSV to succeed
|
||||
kubernetes.core.k8s_info:
|
||||
api_version: operators.coreos.com/v1alpha1
|
||||
kind: ClusterServiceVersion
|
||||
namespace: "{{ cloudnativepg_operator_operator_namespace }}"
|
||||
name: "{{ __cloudnativepg_operator_installplan.resources[0].spec.clusterServiceVersionNames[0] }}"
|
||||
register: __cloudnativepg_operator_csv
|
||||
until: >-
|
||||
__cloudnativepg_operator_csv.resources | length > 0 and
|
||||
__cloudnativepg_operator_csv.resources[0].status.phase | default('') == 'Succeeded'
|
||||
retries: "{{ __cloudnativepg_operator_wait_retries }}"
|
||||
delay: 10
|
||||
|
||||
- name: Wait for CloudNativePG controller manager webhook to be reachable
|
||||
kubernetes.core.k8s_info:
|
||||
api_version: v1
|
||||
kind: Endpoints
|
||||
namespace: "{{ cloudnativepg_operator_operator_namespace }}"
|
||||
name: cnpg-controller-manager-service
|
||||
register: __cloudnativepg_operator_endpoints
|
||||
until: >-
|
||||
__cloudnativepg_operator_endpoints.resources | length > 0 and
|
||||
(__cloudnativepg_operator_endpoints.resources[0].subsets | default([])
|
||||
| map(attribute='addresses', default=[]) | flatten | length) > 0
|
||||
retries: "{{ __cloudnativepg_operator_wait_retries }}"
|
||||
delay: 10
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Step 3: Credential secrets (type kubernetes.io/basic-auth)
|
||||
# ------------------------------------------------------------------
|
||||
- name: Create cluster namespace
|
||||
kubernetes.core.k8s:
|
||||
state: present
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ cloudnativepg_operator_cluster_namespace }}"
|
||||
|
||||
- name: Create postgres credential secrets
|
||||
kubernetes.core.k8s:
|
||||
state: present
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: "{{ item.name }}"
|
||||
namespace: "{{ cloudnativepg_operator_cluster_namespace }}"
|
||||
type: kubernetes.io/basic-auth
|
||||
stringData:
|
||||
username: "{{ cloudnativepg_operator_owner_user }}"
|
||||
password: "{{ __cloudnativepg_operator_password }}"
|
||||
host: "{{ cloudnativepg_operator_cluster_name }}-rw.{{ cloudnativepg_operator_cluster_namespace }}.svc"
|
||||
port: "5432"
|
||||
database: "{{ item.database }}"
|
||||
loop: "{{ cloudnativepg_operator_secrets }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
no_log: "{{ cloudnativepg_operator_no_log }}"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Step 4: PostgreSQL Cluster
|
||||
# ------------------------------------------------------------------
|
||||
- name: Create PostgreSQL Cluster
|
||||
kubernetes.core.k8s:
|
||||
state: present
|
||||
definition:
|
||||
apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
metadata:
|
||||
name: "{{ cloudnativepg_operator_cluster_name }}"
|
||||
namespace: "{{ cloudnativepg_operator_cluster_namespace }}"
|
||||
spec: >-
|
||||
{{
|
||||
{
|
||||
'instances': cloudnativepg_operator_instances,
|
||||
'imageName': cloudnativepg_operator_image_name,
|
||||
'bootstrap': {
|
||||
'initdb': {
|
||||
'owner': cloudnativepg_operator_owner_user,
|
||||
'secret': {'name': cloudnativepg_operator_secrets[0].name},
|
||||
},
|
||||
},
|
||||
'storage': {'size': cloudnativepg_operator_storage_size},
|
||||
}
|
||||
| combine({'storage': {'storageClass': cloudnativepg_operator_storage_class}} if cloudnativepg_operator_storage_class else {}, recursive=True)
|
||||
| combine({'postgresql': {'parameters': {'max_connections': cloudnativepg_operator_max_connections | string}}} if cloudnativepg_operator_max_connections else {}, recursive=True)
|
||||
}}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Step 5: Logical databases
|
||||
# ------------------------------------------------------------------
|
||||
- name: Create Database CRs
|
||||
kubernetes.core.k8s:
|
||||
state: present
|
||||
definition:
|
||||
apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Database
|
||||
metadata:
|
||||
name: "{{ item.name }}"
|
||||
namespace: "{{ cloudnativepg_operator_cluster_namespace }}"
|
||||
spec:
|
||||
name: "{{ item.dbname }}"
|
||||
owner: "{{ cloudnativepg_operator_owner_user }}"
|
||||
cluster:
|
||||
name: "{{ cloudnativepg_operator_cluster_name }}"
|
||||
loop: "{{ cloudnativepg_operator_databases }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
|
||||
- name: Wait for Database CRs to be applied
|
||||
kubernetes.core.k8s_info:
|
||||
api_version: postgresql.cnpg.io/v1
|
||||
kind: Database
|
||||
namespace: "{{ cloudnativepg_operator_cluster_namespace }}"
|
||||
register: __cloudnativepg_operator_databases_status
|
||||
until: >-
|
||||
__cloudnativepg_operator_databases_status.resources | length >= (cloudnativepg_operator_databases | length) and
|
||||
(__cloudnativepg_operator_databases_status.resources
|
||||
| rejectattr('status.applied', 'undefined')
|
||||
| selectattr('status.applied')
|
||||
| list | length) == (__cloudnativepg_operator_databases_status.resources | length)
|
||||
retries: "{{ __cloudnativepg_operator_wait_retries }}"
|
||||
delay: 10
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Step 6: Summary
|
||||
# ------------------------------------------------------------------
|
||||
- name: Display CloudNativePG deployment summary
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "CloudNativePG PostgreSQL cluster ready!"
|
||||
- " Operator namespace : {{ cloudnativepg_operator_operator_namespace }}"
|
||||
- " Cluster : {{ cloudnativepg_operator_cluster_name }} ({{ cloudnativepg_operator_cluster_namespace }})"
|
||||
- " Owner role : {{ cloudnativepg_operator_owner_user }}"
|
||||
- " Databases : {{ cloudnativepg_operator_databases | map(attribute='dbname') | join(', ') }}"
|
||||
- " Credential secrets : {{ cloudnativepg_operator_secrets | map(attribute='name') | join(', ') }}"
|
||||
26
roles/cloudnativepg_operator/tasks/vault_secrets.yml
Normal file
26
roles/cloudnativepg_operator/tasks/vault_secrets.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
# Read the shared postgres owner password from Vault; generate and store it if missing.
|
||||
# Sets __cloudnativepg_operator_password, consumed by the K8s secret tasks in main.yml.
|
||||
|
||||
- name: Read cloudnativepg postgres password from Vault
|
||||
community.hashi_vault.vault_kv2_get:
|
||||
path: "{{ cloudnativepg_operator_vault_path }}"
|
||||
engine_mount_point: "{{ cloudnativepg_operator_vault_mount }}"
|
||||
register: __cloudnativepg_operator_vault_read
|
||||
failed_when: false
|
||||
no_log: "{{ cloudnativepg_operator_no_log }}"
|
||||
|
||||
- name: Resolve postgres password (generate if missing)
|
||||
ansible.builtin.set_fact:
|
||||
__cloudnativepg_operator_password: >-
|
||||
{{ (__cloudnativepg_operator_vault_read.secret | default({})).password
|
||||
| default(lookup('community.general.random_string', length=32, special=false)) }}
|
||||
no_log: "{{ cloudnativepg_operator_no_log }}"
|
||||
|
||||
- name: Write postgres password to Vault
|
||||
community.hashi_vault.vault_kv2_write:
|
||||
path: "{{ cloudnativepg_operator_vault_path }}"
|
||||
engine_mount_point: "{{ cloudnativepg_operator_vault_mount }}"
|
||||
data:
|
||||
password: "{{ __cloudnativepg_operator_password }}"
|
||||
no_log: "{{ cloudnativepg_operator_no_log }}"
|
||||
3
roles/cloudnativepg_operator/vars/main.yml
Normal file
3
roles/cloudnativepg_operator/vars/main.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
# Computed internal variables - do not override
|
||||
__cloudnativepg_operator_wait_retries: "{{ (cloudnativepg_operator_wait_timeout / 10) | int }}"
|
||||
Reference in New Issue
Block a user