Pārlūkot izejas kodu

added pre-flight checks and a basic central deployment role

Grega Bremec 3 gadi atpakaļ
vecāks
revīzija
70163a6b3e

+ 12 - 0
deploy-central.yml

@@ -0,0 +1,12 @@
+
+---
+- name: Make sure central is deployed
+  hosts: workstation.lab.example.com
+  gather_subset: min
+  become: no
+  roles:
+#    - role: check-env
+#      tags: check
+    - role: deploy-central
+      tags: deploy
+...

+ 1 - 1
inventory

@@ -1,4 +1,4 @@
-workstation.lab.example.com
+workstation.lab.example.com ansible_connection=local
 utility.lab.example.com ansible_user=lab
 bastion.lab.example.com ansible_user=root
 

+ 1 - 1
pre-flight.yml

@@ -1,7 +1,7 @@
 ---
 - name: Pre-flight checks only.
   hosts: workstation.lab.example.com
-  gather_facts: no
+  gather_subset: min
   become: no
   roles:
     - role: check-env

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

@@ -0,0 +1,57 @@
+---
+# Variables affecting this role:
+#
+#  tools:
+#    - final_name: the name of the tool to check for
+#      completion: look for bash_completion or no
+#  clusters:
+#
+- name: Check for tools
+  file:
+    path: /usr/local/bin/{{ tools[item].final_name }}
+    state: file
+  loop: "{{ tools.keys() | list }}"
+
+- name: Check for completion files
+  file:
+    path: /etc/bash_completion.d/{{ tools[item].final_name }}.completion
+    state: file
+  when: tools[item].completion
+  loop: "{{ tools.keys() | list }}"
+
+- name: Make sure kubeconfig is there
+  file:
+    path: "{{ ansible_facts['user_dir'] }}/kubeconfig-{{ item }}"
+    state: file
+  loop: "{{ clusters }}"
+
+- name: Make sure pull-secret is there
+  file:
+    path: "{{ ansible_facts['user_dir'] }}/pull-secret"
+    state: file
+
+- name: Verify cluster connectivity
+  kubernetes.core.k8s_cluster_info:
+    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-{{ item }}"
+    validate_certs: no
+  loop: "{{ clusters }}"
+
+- name: Check that the NFS provisioner is there
+  k8s_info:
+    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
+    validate_certs: no
+    api_version: storage.k8s.io/v1
+    kind: StorageClass
+    name: managed-nfs-storage
+  register: sc
+
+- assert:
+    that: (sc.resources | length) == 1
+    fail_msg: "ERROR: No StorageClass called managed-nfs-storage found."
+    success_msg: "OK: StorageClass is there."
+
+- name: "We need python-kubernetes >= 12"
+  become: yes
+  pip:
+    name: kubernetes>=12.0.0
+...

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

@@ -0,0 +1,22 @@
+---
+tools:
+  oc:
+    final_name: oc
+    completion: yes
+  roxctl:
+    final_name: roxctl
+    completion: yes
+  kubelint:
+    final_name: kube-linter
+    completion: yes
+  kubectl:
+    final_name: kubectl
+    completion: yes
+  helm:
+    final_name: helm
+    completion: yes
+clusters:
+  - ocp4
+  - sno1
+  - k3s
+...

+ 4 - 0
roles/deploy-central/defaults/main.yml

@@ -0,0 +1,4 @@
+---
+acs_maj: 3.69
+acs_z: 3.69.0
+...

+ 26 - 0
roles/deploy-central/files/central-cr.yml

@@ -0,0 +1,26 @@
+apiVersion: platform.stackrox.io/v1alpha1
+kind: Central
+metadata:
+  namespace: rhacs
+  name: rhacs
+spec:
+  central:
+    exposure:
+      route:
+        enabled: true
+      loadBalancer:
+        enabled: false
+      nodeport:
+        enabled: false
+    persistence:
+      persistentVolumeClaim:
+        claimName: rhacs-vol
+        size: 100Gi
+        storageClassName: managed-nfs-storage
+  scanner:
+    analyzer:
+      scaling:
+        replicas: 1
+        autoScaling: Disabled
+  egress:
+    connectivityPolicy: Online

+ 188 - 0
roles/deploy-central/tasks/main.yml

@@ -0,0 +1,188 @@
+---
+- name: is there already a subscription?
+  k8s_info:
+    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
+    validate_certs: no
+    api_version: operators.coreos.com/v1alpha1
+    kind: subscription
+    namespace: rhacs
+    name: rhacs
+  register: sub
+
+- name: oi - is there already an operator?
+  k8s_info:
+    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
+    validate_certs: no
+    api_version: operators.coreos.com/v1alpha1
+    kind: clusterserviceversion
+    name: "{{ sub.resources[0].status.installedCSV }}"
+    namespace: rhacs
+  register: csv
+  when:
+    - sub.resources is defined
+    - (sub.resources | length) > 0
+    - sub.resources[0].spec.name == "rhacs-operator"
+    - sub.resources[0].status.installedCSV is defined
+
+- name: assert csv is there
+  set_fact:
+    csv_is_there: true
+
+- name: reset the above fact if not the case
+  set_fact:
+    csv_is_there: false
+  when: (csv is not defined) or (csv.resources | length == 0) or (csv.resources[0].status.phase != "Succeeded")
+
+- name: is there a central pod?
+  k8s_info:
+    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
+    validate_certs: no
+    api_version: v1
+    kind: pod
+    namespace: rhacs
+    label_selectors:
+      - app = central
+  register: central
+
+- name: assert central is there
+  set_fact:
+    central_is_there: true
+
+- name: reset the above fact if not the case
+  set_fact:
+    central_is_there: false
+  when: (central is not defined) or (central.resources | length == 0) or (central.resources[0].status.phase != "Running")
+
+#- name: is there anyone home at the api endpoint?
+
+- name: create ns, og, and sub
+  kubernetes.core.k8s:
+    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
+    validate_certs: no
+    template: templates/central-ns-and-sub.yml
+  when: not csv_is_there
+
+- name: wait until csv is there and ready
+  k8s_info:
+    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
+    validate_certs: no
+    api_version: operators.coreos.com/v1alpha1
+    kind: clusterserviceversion
+    name: rhacs-operator.v{{ acs_z }}
+    namespace: rhacs
+  when: not csv_is_there
+  register: csv
+  until: (csv.resources | length) > 0 and csv.resources[0].status.phase == "Succeeded"
+  retries: 30
+  delay: 5
+
+- name: deploy cr
+  kubernetes.core.k8s:
+    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
+    validate_certs: no
+    src: files/central-cr.yml
+  when: not central_is_there
+
+- name: wait for central pod to be up
+  k8s_info:
+    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
+    validate_certs: no
+    api_version: v1
+    kind: pod
+    namespace: rhacs
+    label_selectors:
+      - app = central
+  when: not central_is_there
+  register: central
+  until: (central.resources | length) > 0 and central.resources[0].status.phase == "Running"
+  retries: 30
+  delay: 5
+
+- name: look up route
+  k8s_info:
+    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
+    validate_certs: no
+    api_version: route.openshift.io/v1
+    kind: route
+    namespace: rhacs
+    name: central
+  register: central_route
+
+- assert:
+    that: central_route.resources | length > 0
+    fail_msg: "ERROR: Central seems to be there, but route is not present."
+    success_msg: "OK, got route to Central."
+
+- name: store route hostname as fact
+  set_fact:
+    central_ep: "{{ central_route.resources[0].spec.host }}"
+
+- name: store the api endpoint in a file
+  copy:
+    dest: "{{ ansible_facts['user_dir'] }}/api-endpoint"
+    content: "{{ central_ep }}:443"
+
+- name: look up secret
+  k8s_info:
+    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
+    validate_certs: no
+    api_version: v1
+    kind: secret
+    namespace: rhacs
+    name: central-htpasswd
+  register: central_secret
+
+- assert:
+    that: central_secret.resources | length > 0
+    fail_msg: "ERROR: Central seems to be there, but auth secret is not present."
+    success_msg: "OK, got secret to Central."
+
+- name: store central pass as fact
+  set_fact:
+    central_pass: "{{ central_secret.resources[0].data.password }}"
+
+- name: store the password in a file
+  copy:
+    dest: "{{ ansible_facts['user_dir'] }}/api-password"
+    content: "{{ central_pass | string | b64decode }}"
+
+- name: does a token exist?
+  uri:
+    method: GET
+    force_basic_auth: true
+    return_content: true
+    validate_certs: false
+    url: "https://{{ central_ep }}/v1/apitokens"
+    url_username: admin
+    url_password: "{{ central_pass | string | b64decode }}"
+    headers:
+      Accept: application/json
+      Content-Type: application/json
+  register: token_list
+
+- name: generate an api token
+  uri:
+    method: POST
+    force_basic_auth: true
+    return_content: true
+    validate_certs: false
+    url: "https://{{ central_ep }}/v1/apitokens/generate"
+    url_username: admin
+    url_password: "{{ central_pass | string | b64decode }}"
+    body: '{"name":"automation","role":null,"roles":["Admin"]}'
+    headers:
+      Accept: application/json
+      Content-Type: application/json
+  register: api_token
+  when: (token_list.json.tokens | items2dict(key_name='name', value_name='revoked'))["automation"] is not defined
+
+- name: store api token in a file
+  copy:
+    dest: "{{ ansible_facts['user_dir'] }}/api-token"
+    content: "{{ api_token.json.token }}"
+  when: not api_token.skipped
+
+#- name: take a policy backup (for later)
+## XXX can't delete system policies XXX
+#
+...

+ 26 - 0
roles/deploy-central/templates/central-ns-and-sub.yml

@@ -0,0 +1,26 @@
+apiVersion: v1
+kind: List
+metadata: {}
+items:
+- apiVersion: v1
+  kind: Namespace
+  metadata:
+    name: rhacs
+- apiVersion: operators.coreos.com/v1
+  kind: OperatorGroup
+  metadata:
+    name: rhacs
+    namespace: rhacs
+  spec:
+    targetNamespaces: []
+- apiVersion: operators.coreos.com/v1alpha1
+  kind: Subscription
+  metadata:
+    name: rhacs
+    namespace: rhacs
+  spec:
+    sourceNamespace: openshift-marketplace
+    source: redhat-operators
+    name: rhacs-operator
+    channel: rhacs-{{ acs_maj }}
+    installPlanApproval: Automatic