---
# 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
