32-quay-deploy.yml 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. ---
  2. # Tasks required by 10-quay-deploy.adoc.
  3. - name: Issue a new Cert for Quay if necessary.
  4. hosts: workstation.lab.example.com
  5. gather_subset: min
  6. tasks:
  7. - name: Check if Quay key exists to save time
  8. ansible.builtin.stat:
  9. path: "{{ ansible_facts['user_dir'] }}/ca/quay-key.pem"
  10. get_attributes: no
  11. get_checksum: no
  12. get_mime: no
  13. register: qkey_file
  14. - name: Check if Quay cert exists to save time
  15. ansible.builtin.stat:
  16. path: "{{ ansible_facts['user_dir'] }}/ca/quay-cert.pem"
  17. get_attributes: no
  18. get_checksum: no
  19. get_mime: no
  20. register: qcert_file
  21. - name: Create a new private key for Quay, if it does not exist yet.
  22. community.crypto.openssl_privatekey:
  23. path: "{{ ansible_facts['user_dir'] }}/ca/quay-key.pem"
  24. type: RSA
  25. size: 4096
  26. mode: 0600
  27. when: qkey_file.stat.exists == false
  28. - name: Create a CSR for Quay
  29. community.crypto.openssl_csr:
  30. path: "{{ ansible_facts['user_dir'] }}/ca/quay-csr.pem"
  31. privatekey_path: "{{ ansible_facts['user_dir'] }}/ca/quay-key.pem"
  32. subject:
  33. C: US
  34. ST: North Carolina
  35. L: Raleigh
  36. O: Red Hat
  37. OU: RHT
  38. CN: registry.ocp4.example.com
  39. use_common_name_for_san: yes
  40. mode: 0600
  41. when: qcert_file.stat.exists == false
  42. - name: Issue a certificate for Quay if one isn't there yet.
  43. ansible.builtin.command:
  44. cmd: openssl ca -config {{ ansible_facts['user_dir'] }}/ca/openssl.cnf -passin pass:verysecret -in {{ ansible_facts['user_dir'] }}/ca/quay-csr.pem -out {{ ansible_facts['user_dir'] }}/ca/quay-cert.pem -batch -notext
  45. creates: "{{ ansible_facts['user_dir'] }}/ca/quay-cert.pem"
  46. - name: Load CA cert and Quay cert.
  47. ansible.builtin.set_fact:
  48. ca_cert: "{{ lookup('file', ansible_facts['user_dir'] + '/ca/ca-cert.pem') }}"
  49. quay_cert: "{{ lookup('file', ansible_facts['user_dir'] + '/ca/lab-ca/newcerts/00.pem') }}"
  50. - name: Concatenate Quay and CA certs.
  51. ansible.builtin.copy:
  52. dest: "{{ ansible_facts['user_dir'] }}/ca/quay-cert.pem"
  53. content: |
  54. {{ quay_cert }}
  55. {{ ca_cert }}
  56. - name: Ensure registry VM has a data directory for Quay.
  57. hosts: registry.ocp4.example.com
  58. become: yes
  59. gather_subset: min
  60. tasks:
  61. - name: Ensure data directory is there.
  62. ansible.builtin.file:
  63. path: /local/quay
  64. mode: 0770
  65. owner: quay
  66. group: quay
  67. state: directory
  68. - name: Configure containers and their environment on registry VM.
  69. hosts: registry.ocp4.example.com
  70. gather_subset: min
  71. remote_user: quay
  72. tasks:
  73. - name: Pull all the images if necessary.
  74. containers.podman.podman_image:
  75. name: "{{ registry_host }}/quay/quay-rhel8:v{{ quay_version }}"
  76. pull: yes
  77. state: present
  78. - name: Create Quay config directory if necessary.
  79. ansible.builtin.file:
  80. path: "{{ ansible_facts['user_dir'] }}/config"
  81. state: directory
  82. mode: 0770
  83. - name: Publish Quay key on registry.
  84. ansible.builtin.copy:
  85. src: /home/student/ca/quay-key.pem
  86. dest: "{{ ansible_facts['user_dir'] }}/config/ssl.key"
  87. mode: 0440
  88. - name: Publish Quay cert on registry.
  89. ansible.builtin.copy:
  90. src: /home/student/ca/quay-cert.pem
  91. dest: "{{ ansible_facts['user_dir'] }}/config/ssl.cert"
  92. mode: 0440
  93. - name: Publish Quay config file.
  94. ansible.builtin.copy:
  95. dest: "{{ ansible_facts['user_dir'] }}/config/config.yaml"
  96. content: |
  97. BUILDLOGS_REDIS:
  98. host: redis
  99. password: verysecret
  100. port: 6379
  101. CREATE_NAMESPACE_ON_PUSH: true
  102. DATABASE_SECRET_KEY: 410c87de-8ad8-4f4c-9670-2ec25bc87191
  103. DB_URI: postgresql://quay:secret@postgresql:5432/quay
  104. DISTRIBUTED_STORAGE_CONFIG:
  105. default:
  106. - LocalStorage
  107. - storage_path: /registry
  108. DISTRIBUTED_STORAGE_DEFAULT_LOCATIONS: []
  109. DISTRIBUTED_STORAGE_PREFERENCE:
  110. - default
  111. FEATURE_MAILING: false
  112. SECRET_KEY: 7ce58d4d-b6f5-4400-ba6b-77b9f728a115
  113. SERVER_HOSTNAME: registry.ocp4.example.com
  114. PREFERRED_URL_SCHEME: https
  115. SETUP_COMPLETE: true
  116. SUPER_USERS:
  117. - admin
  118. TESTING: false
  119. USER_EVENTS_REDIS:
  120. host: redis
  121. password: verysecret
  122. port: 6379
  123. mode: 0660
  124. # TODO: recursive!
  125. - name: Ensure Quay data dirs are owned by the correct user.
  126. become_method: containers.podman.podman_unshare
  127. become: yes
  128. ansible.builtin.file:
  129. path: "{{ item }}"
  130. state: directory
  131. owner: 1001
  132. loop:
  133. - /local/quay
  134. - "{{ ansible_facts['user_dir'] }}/config"
  135. - name: Ensure systemd user dir is there.
  136. ansible.builtin.file:
  137. path: "{{ ansible_facts['user_dir'] }}/.config/systemd/user"
  138. state: directory
  139. - name: Deploy service units.
  140. ansible.builtin.template:
  141. dest: "{{ ansible_facts['user_dir'] }}/.config/systemd/user/quay.service"
  142. src: "templates/quay.service.j2"
  143. - name: Reload systemd.
  144. ansible.builtin.systemd_service:
  145. daemon_reload: yes
  146. scope: user
  147. - name: Enable services and start them.
  148. ansible.builtin.systemd_service:
  149. name: quay
  150. scope: user
  151. state: started
  152. enabled: yes
  153. register: startup
  154. - name: Wait a bit if the Quay container was just started.
  155. ansible.builtin.uri:
  156. method: GET
  157. url: https://registry.ocp4.example.com/
  158. headers:
  159. Accept: application/json
  160. Content-Type: application/json
  161. validate_certs: no
  162. status_code:
  163. - 200
  164. - 404
  165. - 502
  166. when: startup.changed
  167. register: startup_wait
  168. until: startup_wait.status == 200
  169. retries: 30
  170. delay: 5
  171. - name: Check if the admin user exists already.
  172. ansible.builtin.uri:
  173. method: GET
  174. url: https://registry.ocp4.example.com/api/v1/users/admin
  175. headers:
  176. Accept: application/json
  177. Content-Type: application/json
  178. validate_certs: no
  179. status_code:
  180. - 200
  181. - 404
  182. return_content: yes
  183. register: adminuser_is_there
  184. - name: Create an admin user if not yet there.
  185. block:
  186. - name: Obtain an encoded CSRF token.
  187. ansible.builtin.uri:
  188. method: GET
  189. url: https://registry.ocp4.example.com/
  190. headers:
  191. Accept: application/json
  192. Content-Type: application/json
  193. validate_certs: no
  194. return_content: yes
  195. ignore_errors: yes
  196. register: csrf_token_payload
  197. - ansible.builtin.assert:
  198. that:
  199. - csrf_token_payload.cookies['_csrf_token'] is defined
  200. fail_msg: "No CSRF token returned by registry. Can not proceed."
  201. success_msg: "Good, CSRF token found in response."
  202. # In case of issues, run with -v and this will show the raw cookie.
  203. - ansible.builtin.debug:
  204. var: csrf_token_payload.cookies
  205. verbosity: 1
  206. - name: Store the cookie as a new fact. We need it later.
  207. ansible.builtin.set_fact:
  208. csrf_cookie: "{{ csrf_token_payload.cookies['_csrf_token'] }}"
  209. # In case of issues, run with -v and this will show the cookie payload.
  210. - ansible.builtin.debug:
  211. var: csrf_cookie
  212. verbosity: 1
  213. # Must chop out the part of the token before the first dot (the rest is control shit).
  214. # Next, and pad it (==) at the end to have 112 characters (no checking done here).
  215. # Lastly, convert that from JSON to a dict and obtain the value of the token (_csrf_token).
  216. - name: Store CSRF token as a new fact.
  217. ansible.builtin.set_fact:
  218. csrf_token: "{{ (csrf_token_payload.cookies['_csrf_token'] | ansible.builtin.regex_replace('^(\\w+)\\..*$', '\\1==') | ansible.builtin.b64decode | ansible.builtin.from_json)['_csrf_token'] }}"
  219. # In case of issues, run with -v and this will show the decoded token.
  220. - ansible.builtin.debug:
  221. var: csrf_token
  222. verbosity: 1
  223. - name: Send a POST request to registry API to create the admin user.
  224. ansible.builtin.uri:
  225. method: POST
  226. url: https://registry.ocp4.example.com/api/v1/user/
  227. headers:
  228. Accept: application/json
  229. Content-Type: application/json
  230. Cookie: _csrf_token={{ csrf_cookie }}
  231. X-CSRF-Token: "{{ csrf_token }}"
  232. body: |
  233. {
  234. "username": "admin",
  235. "password": "redhat123",
  236. "repeatPassword": "redhat123",
  237. "email": "admin@example.com"
  238. }
  239. body_format: json
  240. validate_certs: no
  241. return_content: yes
  242. register: admin_user_response
  243. # In case of issues, run with -v and this will show the response.
  244. - ansible.builtin.debug:
  245. var: admin_user_response
  246. verbosity: 1
  247. when: adminuser_is_there.status == 404
  248. ...