main.yml 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. ---
  2. # Ensures all the operator artifacts are created and waits for CSV to succeed.
  3. #
  4. # The following variables must exist:
  5. #
  6. # op:
  7. # desired_csv
  8. # op_nsp
  9. # op_cat
  10. # op_pkg
  11. # op_chn
  12. # op_mod
  13. #
  14. # NOTE: Do NOT test by checking for presence of API resources - they do not always get cleaned up.
  15. - debug:
  16. msg: Deploying operator {{ op.op_pkg }} in namespace {{ op.op_nsp }}...
  17. # See if the CSV is available already (anywhere), meaning the operator is already installed.
  18. - name: Check if the CSV exists already
  19. k8s_info:
  20. kubeconfig: tmp/kubeconfig-ocp4
  21. validate_certs: no
  22. api_version: operators.coreos.com/v1alpha1
  23. kind: clusterserviceversion
  24. register: all_csv
  25. - name: Find the wanted CSV among all CSVs
  26. set_fact:
  27. found_csv: '{{ (all_csv | community.general.json_query("resources[?contains(metadata.name, `" + op.op_pkg + ".`)]")) }}'
  28. when:
  29. - all_csv.resources is defined
  30. - (all_csv.resources | length) > 0
  31. - name: Reset CSV data
  32. set_fact:
  33. csv_ns: ''
  34. csv_name: ''
  35. - name: Get details about the CSV if found
  36. set_fact:
  37. csv_ns: "{{ found_csv[0] | community.general.json_query('metadata.namespace') }}"
  38. csv_name: "{{ found_csv[0] | community.general.json_query('metadata.name') }}"
  39. when:
  40. - found_csv is defined
  41. - (found_csv | length) > 0
  42. - debug:
  43. msg: Operator {{ op.op_pkg }} is already installed in {{ csv_ns }} as {{ csv_name }} (desired_csv == {{ op.desired_csv }}).
  44. when:
  45. - csv_ns != ''
  46. - csv_name != ''
  47. - name: Only proceed here if the CSV was not found anywhere yet
  48. block:
  49. # Check if package provides desired_csv in any of the channels
  50. # XXX Due to the idiotic fact that some operators from different catalogs
  51. # have the same manifest name, this needs to be a two-phase query.
  52. # XXX First, query for all operators from the desired catalog.
  53. - name: Get packagemanifests from same catalog
  54. k8s_info:
  55. kubeconfig: tmp/kubeconfig-ocp4
  56. validate_certs: no
  57. api_version: packages.operators.coreos.com/v1
  58. kind: packagemanifest
  59. namespace: openshift-marketplace
  60. label_selectors:
  61. - "catalog = {{ op.op_cat }}"
  62. register: pkg_mft_samecat
  63. # XXX Then, search for the operator that has the status.packageName we need.
  64. - name: Reset pkg_mft before looking for it
  65. set_fact:
  66. pkg_mft: ''
  67. found_chn: ''
  68. - name: Weed out the manifest we need
  69. set_fact:
  70. pkg_mft: '{{ pkg_mft_samecat | community.general.json_query("resources[?status.packageName == `" + op.op_pkg + "`]") }}'
  71. - name: Show what package manifest (if any) was found
  72. debug:
  73. var: pkg_mft
  74. verbosity: 1
  75. - name: Search for any channels that provide desired_csv
  76. set_fact:
  77. found_chn: '{{ (pkg_mft[0] | community.general.json_query("status.channels[?currentCSV == `" + op.desired_csv + "`].name")) }}'
  78. when:
  79. - pkg_mft is defined
  80. - pkg_mft != ''
  81. - pkg_mft | length > 0
  82. - name: Show what channels (if any) have the desired CSV
  83. debug:
  84. var: found_chn
  85. verbosity: 1
  86. - name: Fail if no channel provides the desired_csv
  87. fail:
  88. msg: No {{ op.op_pkg }} channel provides {{ op.desired_csv }}
  89. when:
  90. - found_chn is defined
  91. - found_chn == ''
  92. - name: Fail if selected channel does not provide the desired_csv
  93. fail:
  94. msg: Operator {{ op.op_pkg }} selected channel {{ op.op_chn }} does not provide {{ op.desired_csv }} - {{ found_chn }}
  95. when:
  96. - found_chn is defined
  97. - found_chn != None
  98. - found_chn != ''
  99. - found_chn | length > 0
  100. - op.op_chn not in found_chn
  101. # Create the namespace if necessary
  102. - name: Make sure the namespace is there
  103. k8s:
  104. kubeconfig: tmp/kubeconfig-ocp4
  105. validate_certs: no
  106. api_version: v1
  107. kind: namespace
  108. name: "{{ op.op_nsp }}"
  109. # Check for operator group - if existing, make sure it's compatible; otherwise create it
  110. - name: See if there are any OperatorGroups
  111. k8s_info:
  112. kubeconfig: tmp/kubeconfig-ocp4
  113. validate_certs: no
  114. api_version: operators.coreos.com/v1
  115. kind: operatorgroup
  116. namespace: "{{ op.op_nsp }}"
  117. register: found_opgrp
  118. - name: Die if more than one OG
  119. ansible.builtin.fail:
  120. msg: More than one OperatorGroup found in project.
  121. when: (found_opgrp.resources | length) > 1
  122. - name: Die if op_mod is not recognised
  123. ansible.builtin.fail:
  124. msg: Unrecognised op.op_mod ({{ op.op_mod }})
  125. when: op.op_mod not in ["all", "self"]
  126. - name: Die if op_mod does not match found OG mode
  127. ansible.builtin.fail:
  128. msg: Found OG mode does not match required ({{ op.op_mod }})
  129. when: |
  130. ((found_opgrp.resources | length) == 1 and op.op_mod == "all" and found_opgrp.resources[0].status.namespaces != [""]) or
  131. ((found_opgrp.resources | length) == 1 and op.op_mod == "self" and found_opgrp.resources[0].status.namespaces != [op.op_nsp])
  132. - name: Set fact for namespaces of OG if we require all
  133. set_fact:
  134. og_spec: []
  135. when:
  136. - op.op_mod == "all"
  137. - (found_opgrp.resources | length) == 0
  138. - name: Set fact for namespaces of OG if we require self
  139. set_fact:
  140. og_spec: ["{{op.op_nsp}}"]
  141. when:
  142. - op.op_mod == "self"
  143. - (found_opgrp.resources | length) == 0
  144. - name: Create the OperatorGroup if not there
  145. k8s:
  146. kubeconfig: tmp/kubeconfig-ocp4
  147. validate_certs: no
  148. api_version: operators.coreos.com/v1
  149. kind: operatorgroup
  150. namespace: "{{ op.op_nsp }}"
  151. name: "{{ op.op_nsp }}"
  152. definition:
  153. spec:
  154. targetNamespaces: "{{ og_spec }}"
  155. when: (found_opgrp.resources | length) == 0
  156. # create a subscription if not there, and wait for the CSV
  157. - name: Also make sure there is a subscription
  158. k8s:
  159. kubeconfig: tmp/kubeconfig-ocp4
  160. validate_certs: no
  161. api_version: operators.coreos.com/v1alpha1
  162. kind: subscription
  163. namespace: "{{ op.op_nsp }}"
  164. name: "{{ op.op_pkg }}"
  165. definition:
  166. spec:
  167. source: "{{ op.op_cat }}"
  168. sourceNamespace: openshift-marketplace
  169. name: "{{ op.op_pkg }}"
  170. channel: "{{ op.op_chn }}"
  171. installPlanApproval: Automatic
  172. # TODO: Finish this at some point.
  173. #- name: Wait for installPlan to show up
  174. # k8s_info:
  175. # kubeconfig: tmp/kubeconfig-ocp4
  176. # validate_certs: no
  177. # api_version: operators.coreos.com/v1alpha1
  178. # kind: installplan
  179. # namespace: "{{ op_nsp }}"
  180. # register: installplan
  181. # until:
  182. # - installplan.resources is defined
  183. # - (installplan.resources | length) > 0
  184. # - installplan.resources[0].spec.approved
  185. # retries: 12
  186. # delay: 10
  187. - name: Wait for CSV to show up and complete
  188. k8s_info:
  189. kubeconfig: tmp/kubeconfig-ocp4
  190. validate_certs: no
  191. api_version: operators.coreos.com/v1alpha1
  192. kind: clusterserviceversion
  193. namespace: "{{ op.op_nsp }}"
  194. name: "{{ op.desired_csv }}"
  195. register: new_csv
  196. until:
  197. - new_csv.resources is defined
  198. - (new_csv.resources | length) > 0
  199. - new_csv.resources[0].status is defined
  200. - new_csv.resources[0].status.phase == "Succeeded"
  201. retries: 30
  202. delay: 10
  203. # TODO: Finish this at some point.
  204. #- name: Finally, wait for the pod
  205. # k8s_info:
  206. # kubeconfig: tmp/kubeconfig-ocp4
  207. # validate_certs: no
  208. # api_version: v1
  209. # kind: pod
  210. # namespace: rhsso
  211. # label_selectors:
  212. # - name = rhsso-operator
  213. # register: sso_pod
  214. # until:
  215. # - sso_pod.resources is defined
  216. # - (sso_pod.resources | length) > 0
  217. # - sso_pod.resources[0].status is defined
  218. # - sso_pod.resources[0].status.phase == "Running"
  219. # retries: 30
  220. # delay: 10
  221. - debug:
  222. msg: Operator {{ op.op_pkg }} deployed in namespace {{ op.op_nsp }} with CSV {{ op.desired_csv }}!
  223. when: found_csv is not defined or (found_csv | length) == 0
  224. ...