--- # Playbook to configure OpenShift Cluster using roles - name: Configure OpenShift cluster hosts: localhost connection: local gather_facts: false vars_files: - ../secrets.yml vars: # Skip creating Cloudflare secret in namespace_setup since cert_manager_deployment will handle it skip_cloudflare_secret: true pre_tasks: - name: Ensure required collections are available ansible.builtin.debug: msg: "Ensuring kubernetes.core collection is available in execution environment" - name: Verify cluster variables are set ansible.builtin.assert: that: - cluster_region is defined - cluster_name is defined fail_msg: "Cluster region and name must be defined in inventory" - name: Check if this is a hub cluster ansible.builtin.set_fact: is_hub_cluster: "{{ vars[cluster_region][cluster_name]['is_hub'] | default(false) }}" openshift_default_storage_class: "{{ vars[cluster_region][cluster_name]['storage_class'] | default('forgejo-local-storage') }}" - name: Retrieve kubeadmin password for the cluster ansible.builtin.set_fact: kubeadmin_password: "{{ vars[cluster_region][cluster_name]['kubeadmin_password'] | default('') }}" # Safely extract regions from inventory/secrets without causing recursion - name: Extract region codes from inventory ansible.builtin.set_fact: region_codes: "{{ vars.keys() | select('match', '^[a-z]{3}$') | list }}" roles: # Authentication setup - role: kubernetes_auth tags: - always - auth # Namespace and secrets setup - role: namespace_setup tags: - namespaces - secrets # OAuth and identity provider configuration - role: oauth_configuration tags: - oauth - identity # RBAC setup - role: rbac_setup tags: - rbac - permissions # Cert-manager deployment and configuration # This role must be executed before any roles that create certificates - role: cert_manager_deployment tags: - cert-manager - certificates # API Server Certificate Setup - role: cert_management vars: setup_api_server_cert: true certificate_name: "api-server-cert" certificate_secret_name: "api-server-tls" certificate_common_name: "api.{{ cluster_name }}.{{ cluster_region }}.container.mom" certificate_dns_names: - "api.{{ cluster_name }}.{{ cluster_region }}.container.mom" - "*.apps.{{ cluster_name }}.{{ cluster_region }}.container.mom" tags: - certificates - api-server-cert # Optional hub cluster roles - role: forgejo_deployment vars: forgejo_storage_class_name: "{{ openshift_default_storage_class }}" forgejo_admin_username: "{{ global.forgejo.admin_username | default('forgejo_admin') }}" forgejo_admin_password: "{{ global.forgejo.admin_password | default('forgejo_admin') }}" forgejo_admin_email: "{{ global.forgejo.admin_email | default('forgejo@container.mom') }}" forgejo_db_password: "{{ global.forgejo.db_password | default('forgejo') }}" forgejo_root_url: "https://git.container.mom" forgejo_domain: "git.container.mom" forgejo_ssh_domain: "git.container.mom" when: is_hub_cluster | bool tags: - forgejo - git # Container Mom Operator integration - role: container_mom_operator vars: forgejo_url: "https://git.container.mom" forgejo_org: "container-mom" argocd_namespace: "wkl-argocd" argocd_url: "https://wkl-argocd.apps.{{ cluster_name }}.{{ cluster_region }}.container.mom" base_domain: "apps.{{ cluster_name }}.{{ cluster_region }}.container.mom" openshift_default_storage_class: "{{ openshift_default_storage_class }}" when: is_hub_cluster | bool tags: - container-mom - operator - gitops # ArgoCD deployment - role: argocd_deployment tags: - argocd - gitops # GitOps configuration - role: gitops_configuration vars: repo_url: "https://github.com/pfeifferj/container-mom-go.git" repo_username: "pfeifferj" # Note: repo_password is sourced from global.repo_token in the vault app_of_apps_path: "manifests/00-argocd-app-of-apps-chart" app_of_apps_revision: "main" tags: - gitops - argocd # Managed cluster integration - role: managed_cluster_integration vars: # Pass the dynamically discovered regions managed_regions: "{{ region_codes }}" when: is_hub_cluster | bool tags: - managed-clusters - cluster-secrets post_tasks: # 1. Create ServiceAccount for registry storage initialization - name: Create ServiceAccount for registry storage initialization kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: ServiceAccount metadata: name: registry-storage-init namespace: openshift-image-registry kubeconfig: "{{ k8s_auth_params.kubeconfig }}" validate_certs: "{{ k8s_auth_params.validate_certs }}" # 2. Add privileged SCC to storage init ServiceAccount - name: Add privileged SCC to storage init ServiceAccount kubernetes.core.k8s: state: present definition: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: registry-storage-init-privileged roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:openshift:scc:privileged subjects: - kind: ServiceAccount name: registry-storage-init namespace: openshift-image-registry kubeconfig: "{{ k8s_auth_params.kubeconfig }}" validate_certs: "{{ k8s_auth_params.validate_certs }}" # 3. Initialize registry storage directories with Job - name: Initialize registry storage directories kubernetes.core.k8s: state: present definition: apiVersion: batch/v1 kind: Job metadata: name: registry-storage-init namespace: openshift-image-registry spec: ttlSecondsAfterFinished: 600 template: spec: serviceAccountName: registry-storage-init restartPolicy: Never containers: - name: init-registry-dir image: registry.redhat.io/openshift4/ose-cli:latest command: ["/bin/bash", "-c"] args: - | # Create registry storage directory echo "Creating registry storage directory..." mkdir -p /var/registry chmod 777 /var/registry # Registry typically runs as 1000:1000 chown -R 1000:1000 /var/registry echo "Directory created with permissions:" ls -la /var/registry echo "Registry storage directory created successfully!" securityContext: privileged: true volumeMounts: - name: host-path mountPath: /var volumes: - name: host-path hostPath: path: /var type: Directory # Use worker node selector to match likely hosts nodeSelector: node-role.kubernetes.io/worker: "" kubeconfig: "{{ k8s_auth_params.kubeconfig }}" validate_certs: "{{ k8s_auth_params.validate_certs }}" # 4. Wait for job to complete - name: Wait for storage initialization job to complete kubernetes.core.k8s_info: api_version: batch/v1 kind: Job name: registry-storage-init namespace: openshift-image-registry kubeconfig: "{{ k8s_auth_params.kubeconfig }}" validate_certs: "{{ k8s_auth_params.validate_certs }}" register: job_result until: job_result.resources[0].status.succeeded is defined and job_result.resources[0].status.succeeded == 1 retries: 15 delay: 10 # 5. Create storage class for registry - name: Create storage class for registry kubernetes.core.k8s: state: present definition: apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: registry-storage-class provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer kubeconfig: "{{ k8s_auth_params.kubeconfig }}" validate_certs: "{{ k8s_auth_params.validate_certs }}" # 6. Create PV for registry with node affinity - name: Create PV for registry with node affinity kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: PersistentVolume metadata: name: image-registry-storage spec: capacity: storage: 100Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: registry-storage-class local: path: /var/registry nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: node-role.kubernetes.io/worker operator: Exists kubeconfig: "{{ k8s_auth_params.kubeconfig }}" validate_certs: "{{ k8s_auth_params.validate_certs }}" # 7. Create PVC for registry - name: Create PVC for registry kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: PersistentVolumeClaim metadata: name: image-registry-storage namespace: openshift-image-registry spec: accessModes: - ReadWriteOnce resources: requests: storage: 100Gi storageClassName: registry-storage-class volumeName: image-registry-storage kubeconfig: "{{ k8s_auth_params.kubeconfig }}" validate_certs: "{{ k8s_auth_params.validate_certs }}" # 8. Enable registry with the prepared PVC in one step - name: Enable OpenShift registry with prepared storage kubernetes.core.k8s: state: present definition: apiVersion: imageregistry.operator.openshift.io/v1 kind: Config metadata: name: cluster spec: managementState: Managed storage: pvc: claim: image-registry-storage replicas: 1 kubeconfig: "{{ k8s_auth_params.kubeconfig }}" validate_certs: "{{ k8s_auth_params.validate_certs }}" register: registry_result - name: Wait for registry to become available pause: seconds: 30 when: registry_result.changed | bool # Existing cleanup task - name: Cleanup temporary files ansible.builtin.file: path: "{{ kubeconfig_cleanup_dir }}" state: absent when: kubeconfig_cleanup_required | default(false) ignore_errors: true