Grega Bremec 1 рік тому
коміт
7edaa419c3

+ 12 - 0
ansible.cfg

@@ -0,0 +1,12 @@
+[defaults]
+# required to evade implicit conversion to string in k8s resource_definition
+jinja2_native = True
+inventory = ./inventory.yml
+remote_user = student
+ask_pass = no
+
+[privilege_escalation]
+become = no
+become_method = sudo
+become_askpass = no
+

+ 30 - 0
inventory.yml

@@ -0,0 +1,30 @@
+---
+# A simplistic inventory for the classroom VMs.
+all:
+  hosts:
+    workstation.lab.example.com:
+      ansible_connection: local
+    utility.lab.example.com:
+      ansible_user: lab
+    bastion.lab.example.com:
+      ansible_user: root
+  vars:
+    # OpenShift versions.
+    ocp_maj: "4.10"
+    ocp_z: "4.10.3"
+    # Various AMQ versions.
+    eap_v: "7.4"
+    eap_z: "7.4.12"
+    eap_ch: "stable"
+
+    # These are the tools we need, some also need to be downloaded.
+    tools:
+      oc:
+        final_name: /usr/bin/oc
+        completion: yes
+        completion_file: oc
+
+    # The list of OpenShift clusters check-env will try to connect to.
+    clusters:
+      - ocp4
+...

+ 13 - 0
pre-flight.yml

@@ -0,0 +1,13 @@
+---
+- name: Pre-flight checks only.
+  hosts: workstation.lab.example.com
+  gather_subset: min
+  become: no
+  roles:
+    - role: pull-tools
+      tags: prep
+    - role: check-env
+      tags: check
+    - role: fix-operators
+      tags: fix
+...

+ 5 - 0
roles/check-env/defaults/main.yml

@@ -0,0 +1,5 @@
+---
+# These need to default to something.
+amq_z: "7.11.0"
+amq_ch: "7.11.x"
+...

+ 111 - 0
roles/check-env/tasks/main.yml

@@ -0,0 +1,111 @@
+---
+# Variables affecting this role:
+#
+#  tools:
+#    - final_name: the path to the tool to check for
+#      completion: look for bash_completion or no
+#      completion_file: the name of the bash completion file
+#  clusters:
+#   just a simple list of clusters to check
+#
+- name: Check for tools
+  file:
+    path: "{{ tools[item].final_name }}"
+    state: file
+  loop: "{{ tools.keys() | list }}"
+
+- name: Check for completion files
+  file:
+    path: /etc/bash_completion.d/{{ tools[item].completion_file }}
+    state: file
+  when: tools[item].completion
+  loop: "{{ tools.keys() | list }}"
+
+- name: Make sure kubeconfig is there on utility
+  delegate_to: utility.lab.example.com
+  file:
+    path: /home/lab/{{ item }}/auth/kubeconfig
+    state: file
+  loop: "{{ clusters }}"
+
+- name: Create a temp dir
+  file:
+    path: tmp
+    state: directory
+
+- name: Copy over the kubeconfig
+  delegate_to: utility.lab.example.com
+  fetch:
+    src: /home/lab/{{ item }}/auth/kubeconfig
+    dest: tmp/kubeconfig-{{ item }}
+    flat: yes
+  loop: "{{ clusters }}"
+
+- name: "We need python-kubernetes >= 12"
+  become: yes
+  pip:
+    name: kubernetes>=12.0.0
+
+# XXX This won't do if you install it using pip.
+- name: We also need python38-jmespath
+  become: yes
+  package:
+    name: python38-jmespath
+    state: latest
+
+- name: We need java-17-openjdk-headless, too
+  become: yes
+  package:
+    name: java-17-openjdk-headless
+    state: latest
+
+- name: Get download confirmation code from Google Drive
+  uri:
+    url: "https://drive.google.com/uc?export=download&id={{ amq_file_id }}"
+    creates: "{{ ansible_facts['user_dir'] }}/Downloads/amq-broker-{{ amq_z }}-bin.zip"
+    return_content: yes
+    status_code: 200
+  register: amq_dl_cc
+
+- name: Store conf code as a fact
+  set_fact:
+    amq_src_url: "{{ amq_dl_cc.content | regex_replace('^.*action=\"', '') | regex_replace('\".*$', '') | regex_replace('amp;', '') }}"
+  when: amq_dl_cc.content is defined
+
+- name: Download AMQ broker
+  get_url:
+    url: "{{ amq_src_url }}"
+    dest: "{{ ansible_facts['user_dir'] }}/Downloads/amq-broker-{{ amq_z }}-bin.zip"
+    mode: 0664
+  when: amq_src_url is defined
+
+- name: Extract AMQ broker to /opt
+  become: yes
+  unarchive:
+    src: "{{ ansible_facts['user_dir'] }}/Downloads/amq-broker-{{ amq_z }}-bin.zip"
+    remote_src: yes
+    creates: /opt/amq
+    dest: /opt
+  register: amq_ex_act
+
+- name: Rename wherever the archive extracted into /opt/amq
+  become: yes
+  command: mv /opt/{{ amq_extracted_dir }} /opt/amq
+  when:
+    - amq_ex_act is defined
+    - amq_ex_act.changed
+
+- name: Make sure /opt/amq/bin is in PATH
+  lineinfile:
+    path: "{{ ansible_facts['user_dir'] }}/.bashrc"
+    line: 'PATH="${PATH}:/opt/amq/bin"'
+    regexp: '^PATH=.*/opt/amq/bin'
+    insertafter: "^# User specific environment$"
+    state: present
+
+- name: Verify cluster connectivity
+  kubernetes.core.k8s_cluster_info:
+    kubeconfig: tmp/kubeconfig-{{ item }}
+    validate_certs: no
+  loop: "{{ clusters }}"
+...

+ 12 - 0
roles/check-env/vars/main.yml

@@ -0,0 +1,12 @@
+---
+# need the following variables somewhere in global vars collection:
+# 
+#  - tools
+#  - clusters
+#
+# consult the role tasks file for an explanation
+#
+# Current ID of the AMQ download.
+amq_file_id: 1MISestt2zityvvLYpsMBXuZw5lYQhztB
+amq_extracted_dir: apache-artemis-2.28.0.redhat-00003
+...

Різницю між файлами не показано, бо вона завелика
+ 6 - 0
roles/fix-operators/files/pull-secret.yml


+ 111 - 0
roles/fix-operators/tasks/main.yml

@@ -0,0 +1,111 @@
+---
+# Fixes the openshift-marketplace catalogs by recreating them from original images.
+#
+# Needs the following vars from vars/main.yml:
+#
+#   op_cat          catalog source
+#   op_pkg          operator package name
+#   desired_csv     csv channel we look for
+#   catalog_sources the catalog sources we recreate
+#
+# This is necessary immediately after lab create.
+- name: Wait for the marketplace-operator to be up
+  k8s_info:
+    kubeconfig: tmp/kubeconfig-ocp4
+    validate_certs: no
+    api_version: v1
+    kind: pod
+    namespace: openshift-marketplace
+    label_selectors:
+      - name=marketplace-operator
+  register: mktplc_pod
+  until:
+    - (mktplc_pod.resources | length) == 1
+    - mktplc_pod.resources[0].status.containerStatuses[0].ready
+  retries: 30
+  delay: 10
+
+- name: Make sure the course catalog is not there
+  k8s:
+    kubeconfig: tmp/kubeconfig-ocp4
+    validate_certs: no
+    api_version: operators.coreos.com/v1alpha1
+    kind: catalogsource
+    namespace: openshift-marketplace
+    name: "{{ removed_source }}"
+    state: absent
+
+- name: Make sure the pull secret will do for online sources
+  k8s:
+    kubeconfig: tmp/kubeconfig-ocp4
+    validate_certs: no
+    api_version: v1
+    kind: secret
+    namespace: openshift-config
+    name: pull-secret
+    state: present
+    definition: "{{ lookup('file', 'files/pull-secret.yml') | from_yaml }}"
+
+- name: Ensure the standard catalog sources are there
+  k8s:
+    kubeconfig: tmp/kubeconfig-ocp4
+    validate_certs: no
+    api_version: operators.coreos.com/v1alpha1
+    kind: catalogsource
+    namespace: openshift-marketplace
+    name: "{{ item.name }}"
+    state: present
+    definition:
+      spec:
+        displayName: "{{ item.displ }}"
+        image: "{{ item.image }}"
+        publisher: "Red Hat"
+        sourceType: "grpc"
+  loop: "{{ catalog_sources }}"
+  loop_control:
+    label: "{{ item.displ }}"
+
+- name: Wait for the catalogsources to be ready.
+  k8s_info:
+    kubeconfig: tmp/kubeconfig-ocp4
+    validate_certs: no
+    api_version: operators.coreos.com/v1alpha1
+    kind: catalogsource
+    namespace: openshift-marketplace
+    name: "{{ item.name }}"
+  register: cat_stat
+  until:
+    - (cat_stat.resources | length) == 1
+    - cat_stat.resources[0].status is defined
+    - cat_stat.resources[0].status.connectionState.lastObservedState == "READY"
+  retries: 30
+  delay: 10
+  loop: "{{ catalog_sources }}"
+  loop_control:
+    label: "{{ item.displ }}"
+
+- name: Wait for the amq-broker-rhel8 packagemanifest to appear.
+  k8s_info:
+    kubeconfig: tmp/kubeconfig-ocp4
+    validate_certs: no
+    api_version: packages.operators.coreos.com/v1
+    kind: packagemanifest
+    namespace: openshift-marketplace
+    name: "{{ op_pkg }}"
+  register: op_mft
+  until:
+    - (op_mft.resources | length) == 1
+    - op_mft.resources[0].status.catalogSource == op_cat
+    - op_mft.resources[0].status.packageName == op_pkg
+  retries: 60
+  delay: 10
+
+- assert:
+    that:
+      - op_mft.resources is defined
+      - (op_mft.resources | length) > 0
+      - op_mft.resources[0].status.catalogSource == op_cat
+      - 'desired_csv in (op_mft.resources[0] | community.general.json_query("status.channels[*].currentCSV") | list)'
+    fail_msg: "ERROR: {{ op_pkg }} package manifest not deployed correctly."
+    success_msg: "OK: {{ op_pkg }} package manifest configured correctly."
+...

+ 16 - 0
roles/fix-operators/vars/main.yml

@@ -0,0 +1,16 @@
+---
+op_cat: redhat-operators
+op_pkg: amq-broker-rhel8
+desired_csv: amq-broker-operator.v7.11.0-opr-3
+removed_source: do280-catalog
+catalog_sources:
+  - name: redhat-operators
+    displ: Red Hat Operators
+    image: registry.redhat.io/redhat/redhat-operator-index:v4.10
+  - name: certified-operators
+    displ: Certified Operators
+    image: registry.redhat.io/redhat/certified-operator-index:v4.10
+  - name: community-operators
+    displ: Community Operators
+    image: registry.redhat.io/redhat/community-operator-index:v4.10
+...

+ 109 - 0
roles/pull-tools/tasks/main.yml

@@ -0,0 +1,109 @@
+---
+# Variables affecting this role:
+#
+#  tools:
+#    - final_name: the path to the tool to check for
+#      completion: generate bash_completion or no
+#      completion_file: the name of the bash completion file
+#      download: if no, just skip it
+#      download_filename: the name of the remote file to download
+#      archive_filename: the name of the file inside the archive to extract
+#
+# NOTE: Tools are downloaded from:
+#   - mirror.openshift.com for a specific ocp_z version, if only download_filename is set
+#   - arbitrary location, download_url + download_filename if both are set
+#
+- name: Make sure Downloads exists
+  file:
+    path: "{{ ansible_facts['user_dir'] }}/Downloads"
+    state: directory
+    owner: student
+    group: student
+    mode: 0775
+
+- name: Check whether the tool archive is there
+  stat:
+    path: "{{ ansible_facts['user_dir'] }}/Downloads/{{ tools[item].download_filename }}"
+  when: tools[item].download_filename is defined
+  register: tool_exists
+  loop: "{{ tools.keys() | list }}"
+
+- name: Download the (OpenShift) tool if necessary
+  get_url:
+    dest: "{{ ansible_facts['user_dir'] }}/Downloads/{{ tools[item].download_filename }}"
+    url: "https://mirror.openshift.com/pub/openshift-v4/clients/ocp/{{ ocp_z }}/{{ tools[item].download_filename }}"
+  when:
+    - tools[item].download_url is not defined
+    - tools[item].download_filename is defined
+    - not tool_exists.results[offset].stat.exists
+  register: tool_downloaded
+  loop: "{{ tools.keys() | list }}"
+  loop_control:
+    index_var: offset
+
+- name: Extract the (OpenShift) tool if downloaded
+  become: yes
+  unarchive:
+    src: "{{ ansible_facts['user_dir'] }}/Downloads/{{ tools[item].download_filename }}"
+    remote_src: yes
+    include: "{{ tools[item].archive_filename }}"
+    dest: "{{ tools[item].final_name | dirname }}"
+    owner: root
+    group: root
+    mode: 0755
+  when:
+    - tools[item].download_filename is defined
+    - tools[item].archive_filename is defined
+    - tools[item].final_name is defined
+    - tool_downloaded.results[offset].changed
+  register: tool_extracted
+  loop: "{{ tools.keys() | list }}"
+  loop_control:
+    index_var: offset
+
+- name: Download the (arbitrary) tool if necessary
+  get_url:
+    dest: "{{ ansible_facts['user_dir'] }}/Downloads/{{ tools[item].download_filename }}"
+    url: "{{ tools[item].download_url }}/{{ tools[item].download_filename }}"
+  when:
+    - tools[item].download_url is defined
+    - tools[item].download_filename is defined
+    - not tool_exists.results[offset].stat.exists
+  register: tool_downloaded
+  loop: "{{ tools.keys() | list }}"
+  loop_control:
+    index_var: offset
+
+- name: Extract the (arbitrary) tool if downloaded
+  become: yes
+  unarchive:
+    src: "{{ ansible_facts['user_dir'] }}/Downloads/{{ tools[item].download_filename }}"
+    remote_src: yes
+    include: "{{ tools[item].archive_filename }}"
+    dest: "{{ tools[item].final_name | dirname }}"
+    owner: root
+    group: root
+    mode: 0755
+  when:
+    - tools[item].download_filename is defined
+    - tools[item].archive_filename is defined
+    - tools[item].final_name is defined
+    - tool_downloaded.results[offset].changed
+  register: tool_extracted
+  loop: "{{ tools.keys() | list }}"
+  loop_control:
+    index_var: offset
+
+- name: Generate completion if necessary
+  become: yes
+  shell:
+    cmd: "{{ tools[item].final_name }} completion bash > /etc/bash_completion.d/{{ tools[item].completion_file }}"
+  when:
+    - tools[item].completion
+    - tools[item].completion_file is defined
+    - tools[item].final_name is defined
+    - tool_extracted.results[offset].changed
+  loop: "{{ tools.keys() | list }}"
+  loop_control:
+    index_var: offset
+...

+ 8 - 0
roles/pull-tools/vars/main.yml

@@ -0,0 +1,8 @@
+---
+# need the following variables somewhere in global vars collection:
+# 
+#  - ocp_z
+#  - tools
+#
+# consult the role tasks file for an explanation
+...

Деякі файли не було показано, через те що забагато файлів було змінено