Kaynağa Gözat

add support for missing operators

Grega Bremec 3 hafta önce
ebeveyn
işleme
23742a07f5

+ 23 - 6
playbooks/inventory.yml

@@ -13,12 +13,29 @@ all:
     ocp_maj: "4.18"
     ocp_z: "4.18.6"
 
-    # Operator that needs to be installed.
-    op_cat: redhat-operators
-    op_pkg: amq-streams
-    op_chn: amq-streams-2.9.x
-    op_nsp: openshift-operators
-    desired_csv: amqstreams.v2.9.3-1
+    # Operators that need to be installed.
+    added_operators:
+      - catalog: redhat-operators
+        package: amq-streams
+        channel: amq-streams-2.9.x
+        namespace: openshift-operators
+        desired_csv: amqstreams.v2.9.3-1
+        og_namespaces: []
+        approval: Manual
+      - catalog: redhat-operators
+        package: service-registry-operator
+        channel: 2.x
+        namespace: openshift-operators
+        desired_csv: service-registry-operator.v2.6.13-r2-0.1763986602.p
+        og_namespaces: []
+        approval: Manual
+      - catalog: redhat-operators
+        package: elasticsearch-operator
+        channel: stable-5.8
+        namespace: openshift-operators-redhat
+        desired_csv: elasticsearch-operator.v5.8.21
+        og_namespaces: []
+        approval: Manual
 
     # Some cleanup here.
     removed_operators:

+ 15 - 0
playbooks/pre-flight.yml

@@ -6,23 +6,38 @@
   tasks:
     - include_role:
         name: check-env
+        apply:
+          tags: check
       tags: check
     - include_role:
         name: fix-operators
+        apply:
+          tags: fix
       tags: fix
     - include_role:
         name: remove-operators
+        apply:
+          tags: prep
       loop: "{{ removed_operators }}"
       loop_control:
         loop_var: role
       tags: prep
     - include_role:
         name: deploy-operator
+        apply:
+          tags: prep
+      loop: "{{ added_operators }}"
+      loop_control:
+        loop_var: role
       tags: prep
     - include_role:
         name: install-labs
+        apply:
+          tags: workstation
       tags: workstation
     - include_role:
         name: prep-workspace
+        apply:
+          tags: workstation
       tags: workstation
 ...

+ 0 - 124
playbooks/roles/deploy-operator/tasks/main.yml

@@ -1,124 +0,0 @@
----
-# Ensures all the operator artifacts are created and waits for CSV to succeed.
-#
-# The following variables must exist:
-#
-#   desired_csv
-#   op_nsp
-#   op_cat
-#   op_pkg
-#   op_chn
-#
-# NOTE: Do NOT test by checking for presence of API resources - they do not always get cleaned up.
-#
-# TODO: Maybe someday fix the JSONPath expression below. And figure out why check for a CSV.
-#- name: Check if the CSV exists already
-#  k8s_info:
-#    kubeconfig: tmp/kubeconfig-ocp4
-#    validate_certs: no
-#    api_version: operators.coreos.com/v1alpha1
-#    kind: clusterserviceversion
-#  register: all_csv
-#
-#- name: Find the wanted CSV among all CSVs
-#  set_fact:
-#    found_csv: "{{ (all_csv | community.general.json_query(\"resources[?metadata.name == \" + desired_csv + \"]\")) }}"
-#  when:
-#    - all_csv.resources is defined
-#    - (all_csv.resources | length) > 0
-#
-#- name: Get details about the CSV if found
-#  set_fact:
-#    csv_ns: "{{ found_csv[0] | community.general.json_query('metadata.namespace') }}"
-#    csv_name: "{{ found_csv[0] | community.general.json_query('metadata.name') }}"
-#  when:
-#    - found_csv is defined
-#    - (found_csv | length) > 0
-
-- name: Make sure the namespace is there
-  k8s:
-    kubeconfig: tmp/kubeconfig-ocp4
-    validate_certs: no
-    api_version: v1
-    kind: namespace
-    name: "{{ op_nsp }}"
-
-# TODO: Finish this at some point.
-#- name: Make sure it has a properly configured OperatorGroup
-#  k8s_info:
-#    kubeconfig: tmp/kubeconfig-ocp4
-#    validate_certs: no
-#    api_version: operators.coreos.com/v1
-#    kind: operatorgroup
-#    namespace: "{{ op_nsp }}"
-#  register: found_opgrp
-
-- name: Also make sure there is a subscription
-  k8s:
-    kubeconfig: tmp/kubeconfig-ocp4
-    validate_certs: no
-    api_version: operators.coreos.com/v1alpha1
-    kind: subscription
-    namespace: "{{ op_nsp }}"
-    name: "{{ op_pkg }}"
-    definition:
-      spec:
-        source: "{{ op_cat }}"
-        sourceNamespace: openshift-marketplace
-        name: "{{ op_pkg }}"
-        channel: "{{ op_chn }}"
-        startingCSV: "{{ desired_csv }}"
-        installPlanApproval: Automatic
-
-# TODO: Finish this at some point.
-#- name: Wait for installPlan to show up
-#  k8s_info:
-#    kubeconfig: tmp/kubeconfig-ocp4
-#    validate_certs: no
-#    api_version: operators.coreos.com/v1alpha1
-#    kind: installplan
-#    namespace: "{{ op_nsp }}"
-#  register: installplan
-#  until:
-#    - installplan.resources is defined
-#    - (installplan.resources | length) > 0
-#    - installplan.resources[0].spec.approved
-#  retries: 12
-#  delay: 10
-
-- name: Wait for CSV to show up and complete
-  k8s_info:
-    kubeconfig: tmp/kubeconfig-ocp4
-    validate_certs: no
-    api_version: operators.coreos.com/v1alpha1
-    kind: clusterserviceversion
-    namespace: "{{ op_nsp }}"
-    name: "{{ desired_csv }}"
-  register: new_csv
-  until:
-    - new_csv.resources is defined
-    - (new_csv.resources | length) > 0
-    - new_csv.resources[0].status is defined
-    - new_csv.resources[0].status.phase == "Succeeded"
-  retries: 30
-  delay: 10
-
-# TODO: Finish this at some point.
-#- name: Finally, wait for the pod
-#  k8s_info:
-#    kubeconfig: tmp/kubeconfig-ocp4
-#    validate_certs: no
-#    api_version: v1
-#    kind: pod
-#    namespace: rhsso
-#    label_selectors:
-#      - name = rhsso-operator
-#  register: sso_pod
-#  until:
-#    - sso_pod.resources is defined
-#    - (sso_pod.resources | length) > 0
-#    - sso_pod.resources[0].status is defined
-#    - sso_pod.resources[0].status.phase == "Running"
-#  retries: 30
-#  delay: 10
-...

+ 4 - 0
playbooks/roles/deploy-operators/defaults/main.yml

@@ -0,0 +1,4 @@
+---
+# Variables that are usually overridden.
+kubeadmin_config: "tmp/kubeconfig-ocp4"
+...

+ 202 - 0
playbooks/roles/deploy-operators/tasks/main.yml

@@ -0,0 +1,202 @@
+---
+# Ensures all the operator artifacts are created and waits for CSV to succeed.
+#
+# The following variables must exist:
+#
+#   added_operators:        (list)
+#     - catalog:            the catalog of the manifest
+#       catalog_namespace:  (optional) catalog namespace (defaults to openshift-marketplace)
+#       package:            the name of the packagemanifest
+#       subscription:       the name of the operatorgroup and subscription (optional, defaults to package)
+#       channel:            which channel to install from
+#       namespace:          target namespace for subscription
+#       desired_csv:        for verification - wait for this CSV to appear
+#       og_namespaces:      (list) operatorgroup namespaces
+#       approval:           Automatic (default) or Manual
+#
+# This role must then be applied as:
+#
+#   - include_role:
+#       name: deploy-operators
+#     loop: "{{ added_operators }}"
+#     loop_control:
+#       loop_var: role
+#
+# What this means is that each item of added_operators is expected to be
+# placed in the "role" variable prior to iterating over this role.
+#
+# OPTIONAL:
+#
+#   kubeadmin_config    kubeadmin (or other admin) credentials (tmp/kubeconfig-ocp4)
+#
+# NOTE: Do NOT test by checking for presence of API resources - they do not
+#       always get cleaned up, so it might report a false positive.
+#
+- name: Tell what is happening
+  ansible.builtin.pause:
+    prompt: |
+      *******************************************************************************
+      * Deploying operator {{ role.package }} to namespace {{ role.namespace }}
+      *******************************************************************************
+    seconds: 0
+
+- name: Make sure the namespace is there
+  kubernetes.core.k8s:
+    kubeconfig: "{{ kubeadmin_config }}"
+    validate_certs: no
+    api_version: v1
+    kind: namespace
+    name: "{{ role.namespace }}"
+
+- name: Verify if the namespace has an OperatorGroup already
+  kubernetes.core.k8s_info:
+    kubeconfig: "{{ kubeadmin_config }}"
+    validate_certs: no
+    api_version: operators.coreos.com/v1
+    kind: operatorgroup
+    namespace: "{{ role.namespace }}"
+  register: found_opgrp
+
+- name: Show the operator groups found at verbosity 2+
+  debug:
+    var: found_opgrp
+    verbosity: 2
+
+- name: The OperatorGroup must have a matching targetNamespaces if it exists already, or we can not continue.
+  ansible.builtin.assert:
+    that:
+      - >
+        (role.og_namespaces is defined and
+         found_opgrp.resources[0].spec.targetNamespaces is defined and
+         found_opgrp.resources[0].spec.targetNamespaces == role.og_namespaces) or
+        ((role.og_namespaces is not defined or role.og_namespaces == []) and
+          found_opgrp.resources[0].spec.targetNamespaces is not defined)
+    success_msg: "Found existing OperatorGroup with matching targetNamespaces."
+    fail_msg: "FATAL: OperatorGroup already exists but does not have matching targetNamespaces."
+  when:
+    - found_opgrp.resources is defined
+    - found_opgrp.resources[0] is defined
+    - found_opgrp.resources[0].spec is defined
+
+- name: If not there yet, create an OperatorGroup
+  kubernetes.core.k8s:
+    kubeconfig: "{{ kubeadmin_config }}"
+    validate_certs: no
+    api_version: operators.coreos.com/v1
+    kind: operatorgroup
+    namespace: "{{ role.namespace }}"
+    name: "{{ role.subscription | default(role.package) }}"
+    definition:
+      spec:
+        targetNamespaces: "{{ role.og_namespaces | default(omit) }}"
+  when:
+    - >
+      found_opgrp.resources is not defined or
+      found_opgrp.resources[0] is not defined
+
+- name: Check if installPlans exist already before fondling around with subscriptions
+  kubernetes.core.k8s_info:
+    kubeconfig: "{{ kubeadmin_config }}"
+    validate_certs: no
+    api_version: operators.coreos.com/v1alpha1
+    kind: installplan
+    namespace: "{{ role.namespace }}"
+  register: installplan_pre
+
+- name: Remember the installPlan(s) found prior to fondling around with subscriptions as a fact
+  ansible.builtin.set_fact:
+    sub_ip_pre: "{{ installplan_pre.resources | selectattr('metadata.ownerReferences.0.name', 'in', (role.subscription | default(role.package))) | sort(attribute='metadata.creationTimestamp', reverse=True) }}"
+
+- name: Show the installplan(s) found at verbosity 2+
+  debug:
+    var: sub_ip_pre
+    verbosity: 2
+
+- name: Also make sure there is a subscription
+  kubernetes.core.k8s:
+    kubeconfig: "{{ kubeadmin_config }}"
+    validate_certs: no
+    api_version: operators.coreos.com/v1alpha1
+    kind: subscription
+    namespace: "{{ role.namespace }}"
+    name: "{{ role.subscription | default(role.package) }}"
+    definition:
+      spec:
+        source: "{{ role.catalog }}"
+        sourceNamespace: "{{ role.catalog_namespace | default('openshift-marketplace') }}"
+        name: "{{ role.package }}"
+        channel: "{{ role.channel }}"
+        startingCSV: "{{ role.desired_csv }}"
+        installPlanApproval: "{{ role.approval | default('Automatic') }}"
+  register: subscription
+
+- name: Handle installPlan if the subscription changed anything
+  block:
+    - name: Wait for installPlan to show up
+      kubernetes.core.k8s_info:
+        kubeconfig: "{{ kubeadmin_config }}"
+        validate_certs: no
+        api_version: operators.coreos.com/v1alpha1
+        kind: installplan
+        namespace: "{{ role.namespace }}"
+      register: installplan
+      until:
+        - installplan.resources is defined
+        - (installplan.resources | length) > 0
+        - >
+          (installplan.resources |
+            selectattr('metadata.ownerReferences.0.name', 'in', (role.subscription | default(role.package))) |
+            length) > (sub_ip_pre | length)
+      retries: 12
+      delay: 10
+
+    - name: Remember the installPlan(s) found after the subscription has been modified
+      ansible.builtin.set_fact:
+        sub_ip_post: "{{ installplan.resources | selectattr('metadata.ownerReferences.0.name', 'in', (role.subscription | default(role.package))) | sort(attribute='metadata.creationTimestamp', reverse=True) }}"
+
+    - name: Show the installplan(s) found at verbosity 2+
+      debug:
+        var: sub_ip_post
+        verbosity: 2
+
+    - name: Remember the latest installPlan name as a new fact
+      ansible.builtin.set_fact:
+        latest_install_plan: "{{ sub_ip_post[0].metadata.name }}"
+
+    - name: Announce the installPlan name
+      ansible.builtin.debug:
+        msg: Found installPlan {{ latest_install_plan }}.
+
+    - name: Approve the installPlan if the approval was Manual
+      kubernetes.core.k8s_json_patch:
+        kubeconfig: "{{ kubeadmin_config }}"
+        validate_certs: no
+        api_version: operators.coreos.com/v1alpha1
+        kind: installplan
+        namespace: "{{ role.namespace }}"
+        name: "{{ latest_install_plan }}"
+        patch:
+          - op: replace
+            path: /spec/approved
+            value: true
+      when: role.approval == "Manual"
+
+  when: subscription.changed
+
+- name: Wait for CSV to show up and complete
+  kubernetes.core.k8s_info:
+    kubeconfig: "{{ kubeadmin_config }}"
+    validate_certs: no
+    api_version: operators.coreos.com/v1alpha1
+    kind: clusterserviceversion
+    namespace: "{{ role.namespace }}"
+    name: "{{ role.desired_csv }}"
+  register: new_csv
+  until:
+    - new_csv.resources is defined
+    - (new_csv.resources | length) > 0
+    - new_csv.resources[0].status is defined
+    - new_csv.resources[0].status.phase == "Succeeded"
+  retries: 30
+  delay: 10
+...