diff --git a/config/crd/bases/awx.ansible.com_awxmeshingresses.yaml b/config/crd/bases/awx.ansible.com_awxmeshingresses.yaml index 4203855c8..4ed7edddf 100644 --- a/config/crd/bases/awx.ansible.com_awxmeshingresses.yaml +++ b/config/crd/bases/awx.ansible.com_awxmeshingresses.yaml @@ -20,12 +20,14 @@ spec: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + internal value, and may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + submits requests to. Cannot be updated. In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object @@ -33,6 +35,12 @@ spec: description: Spec defines the desired state of AWXMeshIngress type: object x-kubernetes-preserve-unknown-fields: true + required: + - deployment_name + properties: + deployment_name: + description: Name of the AWX deployment to create the Mesh Ingress for. + type: string status: description: Status defines the observed state of AWXMeshIngress type: object diff --git a/playbooks/awxmeshingress.yml b/playbooks/awxmeshingress.yml deleted file mode 100644 index 7a0295bf5..000000000 --- a/playbooks/awxmeshingress.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- hosts: localhost - gather_facts: no - collections: - - kubernetes.core - - operator_sdk.util - tasks: [] diff --git a/roles/mesh_ingress/defaults/main.yml b/roles/mesh_ingress/defaults/main.yml new file mode 100644 index 000000000..b5fe314a0 --- /dev/null +++ b/roles/mesh_ingress/defaults/main.yml @@ -0,0 +1,4 @@ +deployment_type: awx + +_control_plane_ee_image: quay.io/ansible/awx-ee:latest +_image_pull_policy: Always diff --git a/roles/mesh_ingress/tasks/main.yml b/roles/mesh_ingress/tasks/main.yml new file mode 100644 index 000000000..50c4990b6 --- /dev/null +++ b/roles/mesh_ingress/tasks/main.yml @@ -0,0 +1,90 @@ +--- +- name: Check for presence of AWX instance that we will use to create the Mesh Ingress for. + k8s_info: + api_version: awx.ansible.com/v1beta1 + kind: AWX + name: "{{ deployment_name }}" + namespace: "{{ ansible_operator_meta.namespace }}" + register: awx_instance + +- name: Fail if awx_deployment does not exist in the same namespace + fail: + msg: "AWX instance {{ deployment_name }} does not exist in the same namespace as the AWXMeshIngress instance." + when: awx_instance.resources | length == 0 + +- name: Set awx_spec + set_fact: + awx_spec: "{{ awx_instance.resources[0].spec }}" + +- name: Set user provided control plane ee image + set_fact: + _custom_control_plane_ee_image: "{{ awx_spec.control_plane_ee_image }}" + when: + - awx_spec.control_plane_ee_image | default([]) | length + +- name: Set Control Plane EE image URL + set_fact: + _control_plane_ee_image: "{{ _custom_control_plane_ee_image | default(lookup('env', 'RELATED_IMAGE_CONTROL_PLANE_EE')) | default(_control_plane_ee_image, true) }}" + +- name: Set Image Pull Policy + set_fact: + _image_pull_policy: "{{ awx_spec.image_pull_policy | default(_image_pull_policy, true) }}" + +- name: Apply Route resource + k8s: + apply: yes + definition: "{{ lookup('template', 'route.yml.j2') }}" + wait: yes + wait_timeout: "120" + register: route + +- name: Set external_hostname + set_fact: + external_hostname: "{{ route.result.status.ingress[0].host }}" + +- name: Create other resources + k8s: + apply: yes + definition: "{{ lookup('template', '{{ item }}.yml.j2') }}" + wait: yes + wait_timeout: "120" + loop: + - service_account + - receptor_conf.configmap + - service + - statefulset + +- name: Get the current resource task pod information. + k8s_info: + api_version: v1 + kind: Pod + namespace: '{{ ansible_operator_meta.namespace }}' + label_selectors: + - "app.kubernetes.io/name={{ deployment_name }}-task" + - "app.kubernetes.io/managed-by={{ deployment_type }}-operator" + - "app.kubernetes.io/component={{ deployment_type }}" + field_selectors: + - status.phase=Running + register: awx_task_pod + +- name: Set the resource pod as a variable. + set_fact: + awx_task_pod: >- + {{ awx_task_pod['resources'] + | rejectattr('metadata.deletionTimestamp', 'defined') + | sort(attribute='metadata.creationTimestamp') + | first | default({}) }} + +- name: Set the resource pod name as a variable. + set_fact: + awx_task_pod_name: "{{ awx_task_pod['metadata']['name'] | default('') }}" + +## TODO: awx-manage provision_instance does not currently support peer from control nodes +## !!!dependent on API/CLI changes!!! +# - name: Add new instance to AWX +# k8s_exec: +# namespace: "{{ ansible_operator_meta.namespace }}" +# pod: "{{ awx_task_pod_name }}" +# container: "{{ deployment_name }}-task" +# command: awx-manage provision_instance ... +# register: result diff --git a/roles/mesh_ingress/templates/receptor_conf.configmap.yml.j2 b/roles/mesh_ingress/templates/receptor_conf.configmap.yml.j2 new file mode 100644 index 000000000..a442cb792 --- /dev/null +++ b/roles/mesh_ingress/templates/receptor_conf.configmap.yml.j2 @@ -0,0 +1,22 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ ansible_operator_meta.name }}-receptor-config + namespace: {{ ansible_operator_meta.namespace }} +data: + receptor_conf: | + --- + - node: + id: {{ ansible_operator_meta.name }} + - log-level: debug + - ws-listener: + port: 27199 + tls: tlsserver + - tls-server: + cert: /etc/receptor/tls/receptor.crt + key: /etc/receptor/tls/receptor.key + name: tlsserver + clientcas: /etc/receptor/tls/ca/mesh-CA.crt + requireclientcert: true + mintls13: false diff --git a/roles/mesh_ingress/templates/route.yml.j2 b/roles/mesh_ingress/templates/route.yml.j2 new file mode 100644 index 000000000..493dfe778 --- /dev/null +++ b/roles/mesh_ingress/templates/route.yml.j2 @@ -0,0 +1,19 @@ +--- +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + annotations: + openshift.io/host.generated: "true" + name: {{ ansible_operator_meta.name }} + namespace: {{ ansible_operator_meta.namespace }} +spec: + port: + targetPort: ws + tls: + insecureEdgeTerminationPolicy: None + termination: passthrough + to: + kind: Service + name: {{ ansible_operator_meta.name }} + weight: 100 + wildcardPolicy: None diff --git a/roles/mesh_ingress/templates/service.yml.j2 b/roles/mesh_ingress/templates/service.yml.j2 new file mode 100644 index 000000000..f658308fd --- /dev/null +++ b/roles/mesh_ingress/templates/service.yml.j2 @@ -0,0 +1,14 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ ansible_operator_meta.name }} + namespace: '{{ ansible_operator_meta.namespace }}' +spec: + type: ClusterIP + ports: + - name: ws + port: 27199 + targetPort: 27199 + selector: + statefulset.kubernetes.io/pod-name: {{ ansible_operator_meta.name }}-0 diff --git a/roles/mesh_ingress/templates/service_account.yml.j2 b/roles/mesh_ingress/templates/service_account.yml.j2 new file mode 100644 index 000000000..5a96fa6af --- /dev/null +++ b/roles/mesh_ingress/templates/service_account.yml.j2 @@ -0,0 +1,6 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: '{{ ansible_operator_meta.name }}' + namespace: '{{ ansible_operator_meta.namespace }}' diff --git a/roles/mesh_ingress/templates/statefulset.yml.j2 b/roles/mesh_ingress/templates/statefulset.yml.j2 new file mode 100644 index 000000000..6c0f99ef7 --- /dev/null +++ b/roles/mesh_ingress/templates/statefulset.yml.j2 @@ -0,0 +1,57 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ ansible_operator_meta.name }} + namespace: {{ ansible_operator_meta.namespace }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ ansible_operator_meta.name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ ansible_operator_meta.name }} + spec: + containers: + - args: + - /bin/sh + - -c + - | + internal_hostname={{ ansible_operator_meta.name }} + external_hostname={{ external_hostname }} + receptor --cert-makereq bits=2048 commonname=$internal_hostname dnsname=$internal_hostname dnsname=$external_hostname nodeid=$internal_hostname outreq=/etc/receptor/tls/receptor.req outkey=/etc/receptor/tls/receptor.key + receptor --cert-signreq req=/etc/receptor/tls/receptor.req cacert=/etc/receptor/tls/ca/mesh-CA.crt cakey=/etc/receptor/tls/ca/mesh-CA.key outcert=/etc/receptor/tls/receptor.crt verify=yes + exec receptor --config /etc/receptor/receptor.conf + image: '{{ _control_plane_ee_image }}' + imagePullPolicy: '{{ _image_pull_policy }}' + name: {{ ansible_operator_meta.name }}-mesh-ingress + volumeMounts: + - mountPath: /etc/receptor/receptor.conf + name: {{ ansible_operator_meta.name }}-receptor-config + subPath: receptor.conf + - mountPath: /etc/receptor/tls/ca/mesh-CA.crt + name: {{ ansible_operator_meta.name }}-receptor-ca + readOnly: true + subPath: tls.crt + - mountPath: /etc/receptor/tls/ca/mesh-CA.key + name: {{ ansible_operator_meta.name }}-receptor-ca + readOnly: true + subPath: tls.key + - mountPath: /etc/receptor/tls/ + name: {{ ansible_operator_meta.name }}-receptor-tls + restartPolicy: Always + schedulerName: default-scheduler + serviceAccount: {{ ansible_operator_meta.name }} + volumes: + - name: {{ ansible_operator_meta.name }}-receptor-tls + - name: {{ ansible_operator_meta.name }}-receptor-ca + secret: + defaultMode: 420 + secretName: {{ deployment_name }}-receptor-ca + - configMap: + defaultMode: 420 + items: + - key: receptor_conf + path: receptor.conf + name: {{ ansible_operator_meta.name }}-receptor-config + name: {{ ansible_operator_meta.name }}-receptor-config diff --git a/watches.yaml b/watches.yaml index 3ea931f9e..8e6a5b20b 100644 --- a/watches.yaml +++ b/watches.yaml @@ -25,5 +25,5 @@ - version: v1alpha1 group: awx.ansible.com kind: AWXMeshIngress - playbook: playbooks/awxmeshingress.yml + role: mesh_ingress # +kubebuilder:scaffold:watch