main.yml 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. ---
  2. # Ensures all the operator artifacts are created and waits for CSV to succeed.
  3. #
  4. # The following variables must exist:
  5. #
  6. # added_operators: (list)
  7. # - catalog: the catalog of the manifest
  8. # package: the name of the packagemanifest
  9. # subscription: the name of the operatorgroup and subscription (optional, defaults to package)
  10. # channel: which channel to install from
  11. # namespace: target namespace for subscription
  12. # desired_csv: for verification - wait for this CSV to appear
  13. # og_namespaces: (list) operatorgroup namespaces (XXX not currently used XXX)
  14. # approval: Automatic (default) or Manual
  15. #
  16. # This role must then be applied as:
  17. #
  18. # - include_role:
  19. # name: deploy-operators
  20. # loop: "{{ added_operators }}"
  21. # loop_control:
  22. # loop_var: role
  23. #
  24. # What this means is that each item of added_operators is expected to be
  25. # placed in the "role" variable prior to iterating over this role.
  26. #
  27. # NOTE: Do NOT test by checking for presence of API resources - they do not
  28. # always get cleaned up, so it might report a false positive.
  29. #
  30. - name: Make sure the namespace is there
  31. kubernetes.core.k8s:
  32. kubeconfig: tmp/kubeconfig-ocp4
  33. validate_certs: no
  34. api_version: v1
  35. kind: namespace
  36. name: "{{ role.namespace }}"
  37. - name: Verify if the namespace has an OperatorGroup already
  38. kubernetes.core.k8s_info:
  39. kubeconfig: tmp/kubeconfig-ocp4
  40. validate_certs: no
  41. api_version: operators.coreos.com/v1
  42. kind: operatorgroup
  43. namespace: "{{ role.namespace }}"
  44. register: found_opgrp
  45. - name: Show the operator groups found at verbosity 2+
  46. debug:
  47. var: found_opgrp
  48. verbosity: 2
  49. - name: The OperatorGroup must have a matching targetNamespaces if it exists already, or we can not continue.
  50. ansible.builtin.assert:
  51. that:
  52. - >
  53. (role.og_namespaces is defined and
  54. found_opgrp.resources[0].spec.targetNamespaces is defined and
  55. found_opgrp.resources[0].spec.targetNamespaces == role.og_namespaces) or
  56. ((role.og_namespaces is not defined or role.og_namespaces == []) and
  57. found_opgrp.resources[0].spec.targetNamespaces is not defined)
  58. success_msg: "Found existing OperatorGroup with matching targetNamespaces."
  59. fail_msg: "FATAL: OperatorGroup already exists but does not have matching targetNamespaces."
  60. when:
  61. - found_opgrp.resources is defined
  62. - found_opgrp.resources[0] is defined
  63. - found_opgrp.resources[0].spec is defined
  64. - name: If not there yet, create an OperatorGroup
  65. kubernetes.core.k8s:
  66. kubeconfig: tmp/kubeconfig-ocp4
  67. validate_certs: no
  68. api_version: operators.coreos.com/v1
  69. kind: operatorgroup
  70. namespace: "{{ role.namespace }}"
  71. name: "{{ role.subscription | default(role.package) }}"
  72. definition:
  73. spec:
  74. targetNamespaces: "{{ role.og_namespaces | default(omit) }}"
  75. when:
  76. - >
  77. found_opgrp.resources is not defined or
  78. found_opgrp.resources[0] is not defined
  79. - name: Check if installPlans exist already before fondling around with subscriptions
  80. kubernetes.core.k8s_info:
  81. kubeconfig: tmp/kubeconfig-ocp4
  82. validate_certs: no
  83. api_version: operators.coreos.com/v1alpha1
  84. kind: installplan
  85. namespace: "{{ role.namespace }}"
  86. register: installplan_pre
  87. - name: Remember the installPlan(s) found prior to fondling around with subscriptions as a fact
  88. ansible.builtin.set_fact:
  89. sub_ip_pre: "{{ installplan_pre.resources | selectattr('metadata.ownerReferences.0.name', 'in', (role.subscription | default(role.package))) | sort(attribute='metadata.creationTimestamp', reverse=True) }}"
  90. - name: Show the installplan(s) found at verbosity 2+
  91. debug:
  92. var: sub_ip_pre
  93. verbosity: 2
  94. - name: Also make sure there is a subscription
  95. kubernetes.core.k8s:
  96. kubeconfig: tmp/kubeconfig-ocp4
  97. validate_certs: no
  98. api_version: operators.coreos.com/v1alpha1
  99. kind: subscription
  100. namespace: "{{ role.namespace }}"
  101. name: "{{ role.subscription | default(role.package) }}"
  102. definition:
  103. spec:
  104. source: "{{ role.catalog }}"
  105. sourceNamespace: openshift-marketplace
  106. name: "{{ role.package }}"
  107. channel: "{{ role.channel }}"
  108. startingCSV: "{{ role.desired_csv }}"
  109. installPlanApproval: "{{ role.approval | default('Automatic') }}"
  110. register: subscription
  111. - name: Handle installPlan if the subscription changed anything
  112. block:
  113. - name: Wait for installPlan to show up
  114. kubernetes.core.k8s_info:
  115. kubeconfig: tmp/kubeconfig-ocp4
  116. validate_certs: no
  117. api_version: operators.coreos.com/v1alpha1
  118. kind: installplan
  119. namespace: "{{ role.namespace }}"
  120. register: installplan
  121. until:
  122. - installplan.resources is defined
  123. - (installplan.resources | length) > 0
  124. - >
  125. (installplan.resources |
  126. selectattr('metadata.ownerReferences.0.name', 'in', (role.subscription | default(role.package))) |
  127. length) > (sub_ip_pre | length)
  128. retries: 12
  129. delay: 10
  130. - name: Remember the installPlan(s) found after the subscription has been modified
  131. ansible.builtin.set_fact:
  132. sub_ip_post: "{{ installplan.resources | selectattr('metadata.ownerReferences.0.name', 'in', (role.subscription | default(role.package))) | sort(attribute='metadata.creationTimestamp', reverse=True) }}"
  133. - name: Show the installplan(s) found at verbosity 2+
  134. debug:
  135. var: sub_ip_post
  136. verbosity: 2
  137. - name: Remember the latest installPlan name as a new fact
  138. ansible.builtin.set_fact:
  139. latest_install_plan: "{{ sub_ip_post[0].metadata.name }}"
  140. - name: Announce the installPlan name
  141. ansible.builtin.debug:
  142. msg: Found installPlan {{ latest_install_plan }}
  143. - name: Approve the installPlan if the approval was Manual
  144. kubernetes.core.k8s_json_patch:
  145. kubeconfig: tmp/kubeconfig-ocp4
  146. validate_certs: no
  147. api_version: operators.coreos.com/v1alpha1
  148. kind: installplan
  149. namespace: "{{ role.namespace }}"
  150. name: "{{ latest_install_plan }}"
  151. patch:
  152. - op: replace
  153. path: /spec/approved
  154. value: true
  155. when: role.approval == "Manual"
  156. - name: Remember the installPlan CSV as a fact
  157. ansible.builtin.set_fact:
  158. target_csv: "{{ sub_ip_post[0].spec.clusterServiceVersionNames[0] }}"
  159. - name: Announce the CSV
  160. ansible.builtin.debug:
  161. msg: The installPlan is for {{ target_csv }}
  162. when: subscription.changed
  163. - name: Figure out what CSV the installPlan was for if not first run.
  164. block:
  165. - name: Set a fact for the target_csv
  166. ansible.builtin.set_fact:
  167. target_csv: "{{ (sub_ip_pre | community.general.json_query('[?spec.approved==`true`]'))[0].spec.clusterServiceVersionNames[0] }}"
  168. - name: Announce the CSV
  169. ansible.builtin.debug:
  170. msg: The installPlan is for {{ target_csv }}
  171. when: not subscription.changed
  172. - name: Wait for CSV to show up and complete
  173. kubernetes.core.k8s_info:
  174. kubeconfig: tmp/kubeconfig-ocp4
  175. validate_certs: no
  176. api_version: operators.coreos.com/v1alpha1
  177. kind: clusterserviceversion
  178. namespace: "{{ role.namespace }}"
  179. name: "{{ target_csv }}"
  180. register: new_csv
  181. until:
  182. - new_csv.resources is defined
  183. - (new_csv.resources | length) > 0
  184. - new_csv.resources[0].status is defined
  185. - new_csv.resources[0].status.phase == "Succeeded"
  186. retries: 30
  187. delay: 10
  188. ...