Преглед изворни кода

properly verifying whether a csv (of any version) is already there, checking if selected channel even provides desired_csv

Grega Bremec пре 7 месеци
родитељ
комит
11c76997ce
1 измењених фајлова са 208 додато и 110 уклоњено
  1. 208 110
      playbooks/roles/deploy-operator/tasks/main.yml

+ 208 - 110
playbooks/roles/deploy-operator/tasks/main.yml

@@ -3,121 +3,219 @@
 #
 # The following variables must exist:
 #
-#   desired_csv
-#   op_nsp
-#   op_cat
-#   op_pkg
-#   op_chn
+#   op:
+#     desired_csv
+#     op_nsp
+#     op_cat
+#     op_pkg
+#     op_chn
+#     op_mod
 #
 # 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 }}"
-        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
+
+- debug:
+    msg: Deploying operator {{ op.op_pkg }} in namespace {{ op.op_nsp }}...
+
+# See if the CSV is available already (anywhere), meaning the operator is already installed.
+- name: Check if the CSV exists already
   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
+  register: all_csv
+
+- name: Find the wanted CSV among all CSVs
+  set_fact:
+    found_csv: '{{ (all_csv | community.general.json_query("resources[?contains(metadata.name, `" + op.op_pkg + ".`)]")) }}'
+  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
+
+- debug:
+    msg: Operator {{ op.op_pkg }} is already installed in {{ csv_ns }} as {{ csv_name }} (desired_csv == {{ op.desired_csv }}).
+  when:
+    - csv_ns is defined
+    - csv_name is defined
+
+- name: Only proceed here if the CSV was not found anywhere yet
+  block:
+
+    # Check if package provides desired_csv in any of the channels
+    - name: Get packagemanifest
+      k8s_info:
+        kubeconfig: tmp/kubeconfig-ocp4
+        validate_certs: no
+        api_version: packages.operators.coreos.com/v1
+        kind: packagemanifest
+        namespace: openshift-marketplace
+        name: "{{ op.op_pkg }}"
+      register: pkg_mft
+
+    - name: Search for any channels that provide desired_csv
+      set_fact:
+        found_chn: '{{ (pkg_mft | community.general.json_query("resources[0].status.channels[?currentCSV == `" + op.desired_csv + "`].name")) }}'
+      when:
+        - pkg_mft is defined
+        - pkg_mft.resources | length > 0
+
+    - name: Fail if no channel provides the desired_csv
+      fail:
+        msg: No {{ op.op_pkg }} channel provides {{ op.desired_csv }}
+      when:
+        - found_chn is defined
+        - found_chn | length == 0
+
+    - name: Fail if selected channel does not provide the desired_csv
+      fail:
+        msg: Operator {{ op.op_pkg }} selected channel {{ op.op_chn }} does not provide {{ op.desired_csv }} - {{ found_chn }}
+      when:
+        - found_chn is defined
+        - found_chn | length > 0
+        - op.op_chn not in found_chn
+
+    # Create the namespace if necessary
+    - name: Make sure the namespace is there
+      k8s:
+        kubeconfig: tmp/kubeconfig-ocp4
+        validate_certs: no
+        api_version: v1
+        kind: namespace
+        name: "{{ op.op_nsp }}"
+
+    # Check for operator group - if existing, make sure it's compatible; otherwise create it
+    - name: See if there are any OperatorGroups
+      k8s_info:
+        kubeconfig: tmp/kubeconfig-ocp4
+        validate_certs: no
+        api_version: operators.coreos.com/v1
+        kind: operatorgroup
+        namespace: "{{ op.op_nsp }}"
+      register: found_opgrp
+
+    - name: Die if more than one OG
+      ansible.builtin.fail:
+        msg: More than one OperatorGroup found in project.
+      when: (found_opgrp.resources | length) > 1
+
+    - name: Die if op_mod is not recognised
+      ansible.builtin.fail:
+        msg: Unrecognised op.op_mod ({{ op.op_mod }})
+      when: op.op_mod not in ["all", "self"]
+
+    - name: Die if op_mod does not match found OG mode
+      ansible.builtin.fail:
+        msg: Found OG mode does not match required ({{ op.op_mod }})
+      when: |
+        ((found_opgrp.resources | length) == 1 and op.op_mod == "all" and found_opgrp.resources[0].status.namespaces != [""]) or
+        ((found_opgrp.resources | length) == 1 and op.op_mod == "self" and found_opgrp.resources[0].status.namespaces != [op.op_nsp])
+
+    - name: Set fact for namespaces of OG if we require all
+      set_fact:
+        og_spec: []
+      when:
+        - op.op_mod == "all"
+        - (found_opgrp.resources | length) == 0
+
+    - name: Set fact for namespaces of OG if we require self
+      set_fact:
+        og_spec: ["{{op.op_nsp}}"]
+      when:
+        - op.op_mod == "self"
+        - (found_opgrp.resources | length) == 0
+
+    - name: Create the OperatorGroup if not there
+      k8s:
+        kubeconfig: tmp/kubeconfig-ocp4
+        validate_certs: no
+        api_version: operators.coreos.com/v1
+        kind: operatorgroup
+        namespace: "{{ op.op_nsp }}"
+        name: "{{ op.op_nsp }}"
+        definition:
+          spec:
+            targetNamespaces: "{{ og_spec }}"
+      when: (found_opgrp.resources | length) == 0
+
+    # create a subscription if not there, and wait for the CSV
+    - 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.op_nsp }}"
+        name: "{{ op.op_pkg }}"
+        definition:
+          spec:
+            source: "{{ op.op_cat }}"
+            sourceNamespace: openshift-marketplace
+            name: "{{ op.op_pkg }}"
+            channel: "{{ op.op_chn }}"
+            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.op_nsp }}"
+        name: "{{ op.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
+
+    - debug:
+        msg: Operator {{ op.op_pkg }} deployed in namespace {{ op.op_nsp }} with CSV {{ op.desired_csv }}!
+
+  when: found_csv is not defined or (found_csv | length) == 0
 ...