diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 00000000..8e9f52b9 --- /dev/null +++ b/.ansible-lint @@ -0,0 +1,7 @@ +skip_list: + - '306' + - '602' + - '503' + +exclude_paths: + - deploy/ diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index af7a1e02..96b49383 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,4 +1,4 @@ # These are supported funding model platforms - +--- github: geerlingguy patreon: geerlingguy diff --git a/.travis.yml b/.travis.yml index df7afdd4..a0f0472f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ services: docker language: python install: - - pip3 install docker molecule openshift jmespath + - pip3 install docker molecule yamllint ansible-lint openshift jmespath script: - molecule test -s test-local diff --git a/.yamllint b/.yamllint new file mode 100644 index 00000000..dc24aefb --- /dev/null +++ b/.yamllint @@ -0,0 +1,7 @@ +--- +extends: default +rules: + truthy: disable + line-length: + max: 160 + level: warning diff --git a/README.md b/README.md index ac22861f..14498438 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ Each of these must be appropriately built in preparation for a new tag: Run the following command inside this directory: - operator-sdk build geerlingguy/tower-operator:0.2.1 + operator-sdk build geerlingguy/tower-operator:0.2.3 Then push the generated image to Docker Hub: diff --git a/build/chain-operator-files.yml b/build/chain-operator-files.yml index 34fe1ef1..97ef57b3 100644 --- a/build/chain-operator-files.yml +++ b/build/chain-operator-files.yml @@ -22,7 +22,7 @@ blockinfile: path: "{{ operator_file_path }}" block: "{{ item }}" - marker: "---" + marker: "" marker_begin: "" marker_end: "" insertafter: "EOF" diff --git a/deploy/crds/tower_v1alpha1_tower_cr_awx.yaml b/deploy/crds/tower_v1alpha1_tower_cr_awx.yaml index fa12dd0d..1f35fb52 100644 --- a/deploy/crds/tower_v1alpha1_tower_cr_awx.yaml +++ b/deploy/crds/tower_v1alpha1_tower_cr_awx.yaml @@ -1,3 +1,4 @@ +--- apiVersion: tower.ansible.com/v1alpha1 kind: Tower metadata: diff --git a/deploy/crds/tower_v1alpha1_tower_cr_tower.yaml b/deploy/crds/tower_v1alpha1_tower_cr_tower.yaml index b62f18dc..8d8ed527 100644 --- a/deploy/crds/tower_v1alpha1_tower_cr_tower.yaml +++ b/deploy/crds/tower_v1alpha1_tower_cr_tower.yaml @@ -1,3 +1,4 @@ +--- apiVersion: tower.ansible.com/v1alpha1 kind: Tower metadata: diff --git a/deploy/crds/tower_v1alpha1_tower_crd.yaml b/deploy/crds/tower_v1alpha1_tower_crd.yaml index 2775cae9..a9801b26 100644 --- a/deploy/crds/tower_v1alpha1_tower_crd.yaml +++ b/deploy/crds/tower_v1alpha1_tower_crd.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: @@ -14,6 +15,6 @@ spec: status: {} version: v1alpha1 versions: - - name: v1alpha1 - served: true - storage: true + - name: v1alpha1 + served: true + storage: true diff --git a/deploy/operator.yaml b/deploy/operator.yaml index 44cb9f4f..2f5b38ce 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: Deployment metadata: @@ -16,21 +17,21 @@ spec: containers: - name: ansible command: - - /usr/local/bin/ao-logs - - /tmp/ansible-operator/runner - - stdout + - /usr/local/bin/ao-logs + - /tmp/ansible-operator/runner + - stdout image: "{{ operator_image }}" imagePullPolicy: "{{ pull_policy|default('Always') }}" volumeMounts: - - mountPath: /tmp/ansible-operator/runner - name: runner - readOnly: true + - mountPath: /tmp/ansible-operator/runner + name: runner + readOnly: true - name: operator image: "{{ operator_image }}" imagePullPolicy: "{{ pull_policy|default('Always') }}" volumeMounts: - - mountPath: /tmp/ansible-operator/runner - name: runner + - mountPath: /tmp/ansible-operator/runner + name: runner env: # Watch all namespaces (cluster-scoped). - name: WATCH_NAMESPACE @@ -41,8 +42,6 @@ spec: fieldPath: metadata.name - name: OPERATOR_NAME value: tower-operator - # - name: ANSIBLE_VERBOSITY - # value: '3' volumes: - name: runner emptyDir: {} diff --git a/deploy/role.yaml b/deploy/role.yaml index 73e9eff5..7aadfa5b 100644 --- a/deploy/role.yaml +++ b/deploy/role.yaml @@ -1,64 +1,65 @@ +--- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: creationTimestamp: null name: tower-operator rules: -- apiGroups: - - "" - resources: - - pods - - services - - services/finalizers - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - '*' -- apiGroups: - - apps - - extensions - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - - ingresses - verbs: - - '*' -- apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create -- apiGroups: - - apps - resourceNames: - - tower-operator - resources: - - deployments/finalizers - verbs: - - update -- apiGroups: - - "" - resources: - - pods/exec - verbs: - - create - - get -- apiGroups: - - apps - resources: - - replicasets - verbs: - - get -- apiGroups: - - tower.ansible.com - resources: - - '*' - verbs: - - '*' + - apiGroups: + - "" + resources: + - pods + - services + - services/finalizers + - endpoints + - persistentvolumeclaims + - events + - configmaps + - secrets + verbs: + - '*' + - apiGroups: + - apps + - extensions + resources: + - deployments + - daemonsets + - replicasets + - statefulsets + - ingresses + verbs: + - '*' + - apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - get + - create + - apiGroups: + - apps + resourceNames: + - tower-operator + resources: + - deployments/finalizers + verbs: + - update + - apiGroups: + - "" + resources: + - pods/exec + verbs: + - create + - get + - apiGroups: + - apps + resources: + - replicasets + verbs: + - get + - apiGroups: + - tower.ansible.com + resources: + - '*' + verbs: + - '*' diff --git a/deploy/role_binding.yaml b/deploy/role_binding.yaml index cced2726..69e2fa9a 100644 --- a/deploy/role_binding.yaml +++ b/deploy/role_binding.yaml @@ -1,11 +1,12 @@ +--- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: tower-operator subjects: -- kind: ServiceAccount - name: tower-operator - namespace: default + - kind: ServiceAccount + name: tower-operator + namespace: default roleRef: kind: ClusterRole name: tower-operator diff --git a/deploy/service_account.yaml b/deploy/service_account.yaml index ca8a0dc4..88676b7a 100644 --- a/deploy/service_account.yaml +++ b/deploy/service_account.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ServiceAccount metadata: diff --git a/deploy/tower-operator.yaml b/deploy/tower-operator.yaml index e04900d3..a11677cb 100644 --- a/deploy/tower-operator.yaml +++ b/deploy/tower-operator.yaml @@ -1,107 +1,90 @@ --- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: towers.tower.ansible.com -spec: - group: tower.ansible.com - names: - kind: Tower - listKind: TowerList - plural: towers - singular: tower - scope: Namespaced - subresources: - status: {} - version: v1alpha1 - versions: - - name: v1alpha1 - served: true - storage: true ---- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: creationTimestamp: null name: tower-operator rules: -- apiGroups: - - "" - resources: - - pods - - services - - services/finalizers - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - '*' -- apiGroups: - - apps - - extensions - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - - ingresses - verbs: - - '*' -- apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create -- apiGroups: - - apps - resourceNames: - - tower-operator - resources: - - deployments/finalizers - verbs: - - update -- apiGroups: - - "" - resources: - - pods/exec - verbs: - - create - - get -- apiGroups: - - apps - resources: - - replicasets - verbs: - - get -- apiGroups: - - tower.ansible.com - resources: - - '*' - verbs: - - '*' + - apiGroups: + - "" + resources: + - pods + - services + - services/finalizers + - endpoints + - persistentvolumeclaims + - events + - configmaps + - secrets + verbs: + - '*' + - apiGroups: + - apps + - extensions + resources: + - deployments + - daemonsets + - replicasets + - statefulsets + - ingresses + verbs: + - '*' + - apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - get + - create + - apiGroups: + - apps + resourceNames: + - tower-operator + resources: + - deployments/finalizers + verbs: + - update + - apiGroups: + - "" + resources: + - pods/exec + verbs: + - create + - get + - apiGroups: + - apps + resources: + - replicasets + verbs: + - get + - apiGroups: + - tower.ansible.com + resources: + - '*' + verbs: + - '*' + --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: tower-operator subjects: -- kind: ServiceAccount - name: tower-operator - namespace: default + - kind: ServiceAccount + name: tower-operator + namespace: default roleRef: kind: ClusterRole name: tower-operator apiGroup: rbac.authorization.k8s.io + --- apiVersion: v1 kind: ServiceAccount metadata: name: tower-operator namespace: default + --- apiVersion: apps/v1 kind: Deployment @@ -121,21 +104,21 @@ spec: containers: - name: ansible command: - - /usr/local/bin/ao-logs - - /tmp/ansible-operator/runner - - stdout + - /usr/local/bin/ao-logs + - /tmp/ansible-operator/runner + - stdout image: "geerlingguy/tower-operator:0.2.3" imagePullPolicy: "Always" volumeMounts: - - mountPath: /tmp/ansible-operator/runner - name: runner - readOnly: true + - mountPath: /tmp/ansible-operator/runner + name: runner + readOnly: true - name: operator image: "geerlingguy/tower-operator:0.2.3" imagePullPolicy: "Always" volumeMounts: - - mountPath: /tmp/ansible-operator/runner - name: runner + - mountPath: /tmp/ansible-operator/runner + name: runner env: # Watch all namespaces (cluster-scoped). - name: WATCH_NAMESPACE @@ -146,9 +129,27 @@ spec: fieldPath: metadata.name - name: OPERATOR_NAME value: tower-operator - # - name: ANSIBLE_VERBOSITY - # value: '3' volumes: - name: runner emptyDir: {} ---- \ No newline at end of file + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: towers.tower.ansible.com +spec: + group: tower.ansible.com + names: + kind: Tower + listKind: TowerList + plural: towers + singular: tower + scope: Namespaced + subresources: + status: {} + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true diff --git a/main.yml b/main.yml index f6ded4d3..cc0e4a20 100644 --- a/main.yml +++ b/main.yml @@ -1,3 +1,4 @@ +--- - hosts: localhost gather_facts: no roles: diff --git a/molecule/default/playbook.yml b/molecule/default/converge.yml similarity index 100% rename from molecule/default/playbook.yml rename to molecule/default/converge.yml diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml index 1c21caa8..bff39264 100644 --- a/molecule/default/molecule.yml +++ b/molecule/default/molecule.yml @@ -3,28 +3,25 @@ dependency: name: galaxy driver: name: docker -lint: - name: yamllint - enabled: False +lint: | + yamllint . + ansible-lint platforms: -- name: kind-default - groups: - - k8s - image: bsycorp/kind:latest-1.14 - privileged: True - override_command: no - exposed_ports: - - 8443/tcp - - 10080/tcp - published_ports: - - 0.0.0.0:${TEST_CLUSTER_PORT:-9443}:8443/tcp - pre_build_image: yes + - name: kind-default + groups: + - k8s + image: bsycorp/kind:latest-1.14 + privileged: True + override_command: no + exposed_ports: + - 8443/tcp + - 10080/tcp + published_ports: + - 0.0.0.0:${TEST_CLUSTER_PORT:-9443}:8443/tcp + pre_build_image: yes provisioner: name: ansible log: True - lint: - name: ansible-lint - enabled: False inventory: group_vars: all: @@ -34,9 +31,3 @@ provisioner: KUBECONFIG: /tmp/molecule/kind-default/kubeconfig ANSIBLE_ROLES_PATH: ${MOLECULE_PROJECT_DIRECTORY}/roles KIND_PORT: '${TEST_CLUSTER_PORT:-9443}' -scenario: - name: default -verifier: - name: testinfra - lint: - name: flake8 diff --git a/molecule/default/prepare.yml b/molecule/default/prepare.yml index 6aecea32..63a617be 100644 --- a/molecule/default/prepare.yml +++ b/molecule/default/prepare.yml @@ -8,21 +8,21 @@ deploy_dir: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/deploy" tasks: - - name: Create Custom Resource Definition - k8s: - definition: "{{ lookup('file', '/'.join([deploy_dir, 'crds/tower_v1alpha1_tower_crd.yaml'])) }}" + - name: Create Custom Resource Definition + k8s: + definition: "{{ lookup('file', '/'.join([deploy_dir, 'crds/tower_v1alpha1_tower_crd.yaml'])) }}" - - name: Ensure specified namespace is present - k8s: - api_version: v1 - kind: Namespace - name: '{{ operator_namespace }}' + - name: Ensure specified namespace is present + k8s: + api_version: v1 + kind: Namespace + name: '{{ operator_namespace }}' - - name: Create RBAC resources - k8s: - definition: "{{ lookup('template', '/'.join([deploy_dir, item])) }}" - namespace: '{{ operator_namespace }}' - with_items: - - role.yaml - - role_binding.yaml - - service_account.yaml + - name: Create RBAC resources + k8s: + definition: "{{ lookup('template', '/'.join([deploy_dir, item])) }}" + namespace: '{{ operator_namespace }}' + with_items: + - role.yaml + - role_binding.yaml + - service_account.yaml diff --git a/molecule/test-local/converge.yml b/molecule/test-local/converge.yml new file mode 100644 index 00000000..4be8b8e8 --- /dev/null +++ b/molecule/test-local/converge.yml @@ -0,0 +1,130 @@ +--- +- name: Build Operator in Kind container + hosts: k8s + + vars: + image_name: tower.ansible.com/tower-operator:testing + + tasks: + # using command so we don't need to install any dependencies + - name: Get existing image hash + command: docker images -q {{ image_name }} + register: prev_hash + changed_when: false + + - name: Build Operator Image + command: docker build -f /build/build/Dockerfile -t {{ image_name }} /build + register: build_cmd + changed_when: not prev_hash.stdout or (prev_hash.stdout and prev_hash.stdout not in ''.join(build_cmd.stdout_lines[-2:])) + +- name: Converge + hosts: localhost + connection: local + + vars: + ansible_python_interpreter: '{{ ansible_playbook_python }}' + deploy_dir: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/deploy" + pull_policy: Never + operator_image: tower.ansible.com/tower-operator:testing + custom_resource: "{{ lookup('file', '/'.join([deploy_dir, 'crds/tower_v1alpha1_tower_cr_awx.yaml'])) | from_yaml }}" + + tasks: + + - block: + + - name: Delete the Operator Deployment + k8s: + state: absent + namespace: '{{ operator_namespace }}' + definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) }}" + register: delete_deployment + when: hostvars[groups.k8s.0].build_cmd.changed + + - name: Wait 30s for Operator Deployment to terminate + k8s_info: + api_version: '{{ definition.apiVersion }}' + kind: '{{ definition.kind }}' + namespace: '{{ operator_namespace }}' + name: '{{ definition.metadata.name }}' + vars: + definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) | from_yaml }}" + register: deployment + until: not deployment.resources + delay: 3 + retries: 10 + when: delete_deployment.changed + + - name: Create the Operator Deployment + k8s: + namespace: '{{ operator_namespace }}' + definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) }}" + + - name: Ensure the Tower custom_resource namespace exists + k8s: + state: present + name: '{{ custom_resource.metadata.namespace }}' + kind: Namespace + api_version: v1 + + - name: Create the tower.ansible.com/v1alpha1.Tower + k8s: + state: present + namespace: '{{ custom_resource.metadata.namespace }}' + definition: '{{ custom_resource }}' + + - name: Wait 15m for reconciliation to run + k8s_info: + api_version: '{{ custom_resource.apiVersion }}' + kind: '{{ custom_resource.kind }}' + namespace: '{{ custom_resource.metadata.namespace }}' + name: '{{ custom_resource.metadata.name }}' + register: cr + until: + - "'Successful' in (cr | json_query('resources[].status.conditions[].reason'))" + delay: 6 + retries: 150 + + rescue: + + - name: debug cr + ignore_errors: yes + failed_when: false + debug: + var: debug_cr + vars: + debug_cr: '{{ lookup("k8s", + kind=custom_resource.kind, + api_version=custom_resource.apiVersion, + namespace=custom_resource.metadata.namespace, + resource_name=custom_resource.metadata.name + )}}' + + - name: debug tower deployment + ignore_errors: yes + failed_when: false + debug: + var: deploy + vars: + deploy: '{{ lookup("k8s", + kind="Deployment", + api_version="apps/v1", + namespace=custom_resource.metadata.namespace, + label_selector="app=tower" + )}}' + + - name: get operator logs + ignore_errors: yes + failed_when: false + command: kubectl logs deployment/{{ definition.metadata.name }} -n {{ operator_namespace }} -c operator + environment: + KUBECONFIG: '{{ lookup("env", "KUBECONFIG") }}' + vars: + definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) | from_yaml }}" + register: log + + - debug: var=log.stdout_lines + + - fail: + msg: "Failed on action: converge" + +- import_playbook: '{{ playbook_dir }}/../default/asserts.yml' diff --git a/molecule/test-local/molecule.yml b/molecule/test-local/molecule.yml index e4c57821..e5d88956 100644 --- a/molecule/test-local/molecule.yml +++ b/molecule/test-local/molecule.yml @@ -3,30 +3,27 @@ dependency: name: galaxy driver: name: docker -lint: - name: yamllint - enabled: False +lint: | + yamllint . + ansible-lint platforms: -- name: kind-test-local - groups: - - k8s - image: bsycorp/kind:latest-1.15 - privileged: True - override_command: no - exposed_ports: - - 8443/tcp - - 10080/tcp - published_ports: - - 0.0.0.0:${TEST_CLUSTER_PORT:-10443}:8443/tcp - pre_build_image: yes - volumes: - - ${MOLECULE_PROJECT_DIRECTORY}:/build:Z + - name: kind-test-local + groups: + - k8s + image: bsycorp/kind:latest-1.15 + privileged: True + override_command: no + exposed_ports: + - 8443/tcp + - 10080/tcp + published_ports: + - 0.0.0.0:${TEST_CLUSTER_PORT:-10443}:8443/tcp + pre_build_image: yes + volumes: + - ${MOLECULE_PROJECT_DIRECTORY}:/build:Z provisioner: name: ansible log: True - lint: - name: ansible-lint - enabled: False inventory: group_vars: all: @@ -37,7 +34,6 @@ provisioner: ANSIBLE_ROLES_PATH: ${MOLECULE_PROJECT_DIRECTORY}/roles KIND_PORT: '${TEST_CLUSTER_PORT:-10443}' scenario: - name: test-local test_sequence: - lint - destroy @@ -46,10 +42,4 @@ scenario: - create - prepare - converge - - side_effect - - verify - destroy -verifier: - name: testinfra - lint: - name: flake8 diff --git a/molecule/test-local/playbook.yml b/molecule/test-local/playbook.yml deleted file mode 100644 index ebfdf32d..00000000 --- a/molecule/test-local/playbook.yml +++ /dev/null @@ -1,130 +0,0 @@ ---- -- name: Build Operator in Kind container - hosts: k8s - - vars: - image_name: tower.ansible.com/tower-operator:testing - - tasks: - # using command so we don't need to install any dependencies - - name: Get existing image hash - command: docker images -q {{ image_name }} - register: prev_hash - changed_when: false - - - name: Build Operator Image - command: docker build -f /build/build/Dockerfile -t {{ image_name }} /build - register: build_cmd - changed_when: not prev_hash.stdout or (prev_hash.stdout and prev_hash.stdout not in ''.join(build_cmd.stdout_lines[-2:])) - -- name: Converge - hosts: localhost - connection: local - - vars: - ansible_python_interpreter: '{{ ansible_playbook_python }}' - deploy_dir: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/deploy" - pull_policy: Never - operator_image: tower.ansible.com/tower-operator:testing - custom_resource: "{{ lookup('file', '/'.join([deploy_dir, 'crds/tower_v1alpha1_tower_cr_awx.yaml'])) | from_yaml }}" - - tasks: - - - block: - - - name: Delete the Operator Deployment - k8s: - state: absent - namespace: '{{ operator_namespace }}' - definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) }}" - register: delete_deployment - when: hostvars[groups.k8s.0].build_cmd.changed - - - name: Wait 30s for Operator Deployment to terminate - k8s_info: - api_version: '{{ definition.apiVersion }}' - kind: '{{ definition.kind }}' - namespace: '{{ operator_namespace }}' - name: '{{ definition.metadata.name }}' - vars: - definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) | from_yaml }}" - register: deployment - until: not deployment.resources - delay: 3 - retries: 10 - when: delete_deployment.changed - - - name: Create the Operator Deployment - k8s: - namespace: '{{ operator_namespace }}' - definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) }}" - - - name: Ensure the Tower custom_resource namespace exists - k8s: - state: present - name: '{{ custom_resource.metadata.namespace }}' - kind: Namespace - api_version: v1 - - - name: Create the tower.ansible.com/v1alpha1.Tower - k8s: - state: present - namespace: '{{ custom_resource.metadata.namespace }}' - definition: '{{ custom_resource }}' - - - name: Wait 15m for reconciliation to run - k8s_info: - api_version: '{{ custom_resource.apiVersion }}' - kind: '{{ custom_resource.kind }}' - namespace: '{{ custom_resource.metadata.namespace }}' - name: '{{ custom_resource.metadata.name }}' - register: cr - until: - - "'Successful' in (cr | json_query('resources[].status.conditions[].reason'))" - delay: 6 - retries: 150 - - rescue: - - - name: debug cr - ignore_errors: yes - failed_when: false - debug: - var: debug_cr - vars: - debug_cr: '{{ lookup("k8s", - kind=custom_resource.kind, - api_version=custom_resource.apiVersion, - namespace=custom_resource.metadata.namespace, - resource_name=custom_resource.metadata.name - )}}' - - - name: debug tower deployment - ignore_errors: yes - failed_when: false - debug: - var: deploy - vars: - deploy: '{{ lookup("k8s", - kind="Deployment", - api_version="apps/v1", - namespace=custom_resource.metadata.namespace, - label_selector="app=tower" - )}}' - - - name: get operator logs - ignore_errors: yes - failed_when: false - command: kubectl logs deployment/{{ definition.metadata.name }} -n {{ operator_namespace }} -c operator - environment: - KUBECONFIG: '{{ lookup("env", "KUBECONFIG") }}' - vars: - definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) | from_yaml }}" - register: log - - - debug: var=log.stdout_lines - - - fail: - msg: "Failed on action: converge" - -- import_playbook: '{{ playbook_dir }}/../default/asserts.yml' diff --git a/molecule/test-minikube/converge.yml b/molecule/test-minikube/converge.yml new file mode 100644 index 00000000..786d018e --- /dev/null +++ b/molecule/test-minikube/converge.yml @@ -0,0 +1,136 @@ +--- +# TODO: For some reason prepare is not run after a destroy in the Minikube env. +- import_playbook: ../default/prepare.yml + +- name: Build Operator in Minikube + hosts: localhost + connection: local + + vars: + image_name: tower.ansible.com/tower-operator:testing + + tasks: + # Use raw Docker commands inside Minikube to avoid extra Python dependencies. + - name: Get existing image hash + shell: | + eval $(minikube docker-env) + docker images -q {{ image_name }} + register: prev_hash + changed_when: false + + - name: Build Operator Image + shell: | + eval $(minikube docker-env) + docker build -f ../../build/Dockerfile -t {{ image_name }} ../.. + register: build_cmd + changed_when: not prev_hash.stdout or (prev_hash.stdout and prev_hash.stdout not in ''.join(build_cmd.stdout_lines[-2:])) + +- name: Converge + hosts: localhost + connection: local + + vars: + ansible_python_interpreter: '{{ ansible_playbook_python }}' + deploy_dir: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/deploy" + pull_policy: Never + operator_image: tower.ansible.com/tower-operator:testing + custom_resource: "{{ lookup('file', '/'.join([deploy_dir, 'crds/tower_v1alpha1_tower_cr_tower.yaml'])) | from_yaml }}" + + tasks: + - block: + - name: Delete the Operator Deployment + k8s: + state: absent + namespace: '{{ operator_namespace }}' + definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) }}" + register: delete_deployment + when: build_cmd.changed + + - name: Wait 30s for Operator Deployment to terminate + k8s_info: + api_version: '{{ definition.apiVersion }}' + kind: '{{ definition.kind }}' + namespace: '{{ operator_namespace }}' + name: '{{ definition.metadata.name }}' + vars: + definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) | from_yaml }}" + register: deployment + until: not deployment.resources + delay: 3 + retries: 10 + when: delete_deployment.changed + + - name: Create the Operator Deployment + k8s: + namespace: '{{ operator_namespace }}' + definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) }}" + + - name: Ensure the Tower custom_resource namespace exists + k8s: + state: present + name: '{{ custom_resource.metadata.namespace }}' + kind: Namespace + api_version: v1 + + - name: Create the tower.ansible.com/v1alpha1.Tower + k8s: + state: present + namespace: '{{ custom_resource.metadata.namespace }}' + definition: '{{ custom_resource }}' + + - name: Wait 15m for reconciliation to run + k8s_info: + api_version: '{{ custom_resource.apiVersion }}' + kind: '{{ custom_resource.kind }}' + namespace: '{{ custom_resource.metadata.namespace }}' + name: '{{ custom_resource.metadata.name }}' + register: cr + until: + - "'Successful' in (cr | json_query('resources[].status.conditions[].reason'))" + delay: 6 + retries: 150 + + rescue: + + - name: debug cr + ignore_errors: yes + failed_when: false + debug: + var: debug_cr + vars: + debug_cr: '{{ lookup("k8s", + kind=custom_resource.kind, + api_version=custom_resource.apiVersion, + namespace=custom_resource.metadata.namespace, + resource_name=custom_resource.metadata.name + )}}' + + - name: debug tower deployment + ignore_errors: yes + failed_when: false + debug: + var: deploy + vars: + deploy: '{{ lookup("k8s", + kind="Deployment", + api_version="apps/v1", + namespace=custom_resource.metadata.namespace, + label_selector="app=tower" + )}}' + + - name: get operator logs + ignore_errors: yes + failed_when: false + command: kubectl logs deployment/{{ definition.metadata.name }} -n {{ operator_namespace }} -c operator + environment: + KUBECONFIG: '{{ lookup("env", "KUBECONFIG") }}' + vars: + definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) | from_yaml }}" + register: log + + - debug: var=log.stdout_lines + + - fail: + msg: "Failed on action: converge" + +- import_playbook: '{{ playbook_dir }}/../default/asserts.yml' diff --git a/molecule/test-minikube/molecule.yml b/molecule/test-minikube/molecule.yml index b43809f3..1045d16e 100644 --- a/molecule/test-minikube/molecule.yml +++ b/molecule/test-minikube/molecule.yml @@ -6,26 +6,22 @@ driver: options: managed: False ansible_connection_options: {} -lint: - name: yamllint - enabled: False +lint: | + yamllint . + ansible-lint platforms: -- name: test-minikube - groups: - - k8s + - name: test-minikube + groups: + - k8s provisioner: name: ansible inventory: group_vars: all: operator_namespace: ${TEST_NAMESPACE:-default} - lint: - name: ansible-lint - enabled: False env: ANSIBLE_ROLES_PATH: ${MOLECULE_PROJECT_DIRECTORY}/roles scenario: - name: test-minikube test_sequence: - lint - destroy @@ -34,10 +30,4 @@ scenario: - create - prepare - converge - - side_effect - - verify - destroy -verifier: - name: testinfra - lint: - name: flake8 diff --git a/molecule/test-minikube/playbook.yml b/molecule/test-minikube/playbook.yml deleted file mode 100644 index ae6a37c0..00000000 --- a/molecule/test-minikube/playbook.yml +++ /dev/null @@ -1,136 +0,0 @@ ---- -# TODO: For some reason prepare is not run after a destroy in the Minikube env. -- import_playbook: ../default/prepare.yml - -- name: Build Operator in Minikube - hosts: localhost - connection: local - - vars: - image_name: tower.ansible.com/tower-operator:testing - - tasks: - # Use raw Docker commands inside Minikube to avoid extra Python dependencies. - - name: Get existing image hash - shell: | - eval $(minikube docker-env) - docker images -q {{ image_name }} - register: prev_hash - changed_when: false - - - name: Build Operator Image - shell: | - eval $(minikube docker-env) - docker build -f ../../build/Dockerfile -t {{ image_name }} ../.. - register: build_cmd - changed_when: not prev_hash.stdout or (prev_hash.stdout and prev_hash.stdout not in ''.join(build_cmd.stdout_lines[-2:])) - -- name: Converge - hosts: localhost - connection: local - - vars: - ansible_python_interpreter: '{{ ansible_playbook_python }}' - deploy_dir: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/deploy" - pull_policy: Never - operator_image: tower.ansible.com/tower-operator:testing - custom_resource: "{{ lookup('file', '/'.join([deploy_dir, 'crds/tower_v1alpha1_tower_cr_tower.yaml'])) | from_yaml }}" - - tasks: - - block: - - name: Delete the Operator Deployment - k8s: - state: absent - namespace: '{{ operator_namespace }}' - definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) }}" - register: delete_deployment - when: build_cmd.changed - - - name: Wait 30s for Operator Deployment to terminate - k8s_info: - api_version: '{{ definition.apiVersion }}' - kind: '{{ definition.kind }}' - namespace: '{{ operator_namespace }}' - name: '{{ definition.metadata.name }}' - vars: - definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) | from_yaml }}" - register: deployment - until: not deployment.resources - delay: 3 - retries: 10 - when: delete_deployment.changed - - - name: Create the Operator Deployment - k8s: - namespace: '{{ operator_namespace }}' - definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) }}" - - - name: Ensure the Tower custom_resource namespace exists - k8s: - state: present - name: '{{ custom_resource.metadata.namespace }}' - kind: Namespace - api_version: v1 - - - name: Create the tower.ansible.com/v1alpha1.Tower - k8s: - state: present - namespace: '{{ custom_resource.metadata.namespace }}' - definition: '{{ custom_resource }}' - - - name: Wait 15m for reconciliation to run - k8s_info: - api_version: '{{ custom_resource.apiVersion }}' - kind: '{{ custom_resource.kind }}' - namespace: '{{ custom_resource.metadata.namespace }}' - name: '{{ custom_resource.metadata.name }}' - register: cr - until: - - "'Successful' in (cr | json_query('resources[].status.conditions[].reason'))" - delay: 6 - retries: 150 - - rescue: - - - name: debug cr - ignore_errors: yes - failed_when: false - debug: - var: debug_cr - vars: - debug_cr: '{{ lookup("k8s", - kind=custom_resource.kind, - api_version=custom_resource.apiVersion, - namespace=custom_resource.metadata.namespace, - resource_name=custom_resource.metadata.name - )}}' - - - name: debug tower deployment - ignore_errors: yes - failed_when: false - debug: - var: deploy - vars: - deploy: '{{ lookup("k8s", - kind="Deployment", - api_version="apps/v1", - namespace=custom_resource.metadata.namespace, - label_selector="app=tower" - )}}' - - - name: get operator logs - ignore_errors: yes - failed_when: false - command: kubectl logs deployment/{{ definition.metadata.name }} -n {{ operator_namespace }} -c operator - environment: - KUBECONFIG: '{{ lookup("env", "KUBECONFIG") }}' - vars: - definition: "{{ lookup('template', '/'.join([deploy_dir, 'operator.yaml'])) | from_yaml }}" - register: log - - - debug: var=log.stdout_lines - - - fail: - msg: "Failed on action: converge" - -- import_playbook: '{{ playbook_dir }}/../default/asserts.yml' diff --git a/roles/tower/meta/main.yml b/roles/tower/meta/main.yml index 5eed649f..4f89975d 100644 --- a/roles/tower/meta/main.yml +++ b/roles/tower/meta/main.yml @@ -1,3 +1,4 @@ +--- galaxy_info: author: Jeff Geerling description: Tower role for Tower Operator for Kubernetes. @@ -7,6 +8,14 @@ galaxy_info: min_ansible_version: 2.8 + platforms: + - name: EL + versions: + - all + - name: Debian + versions: + - all + galaxy_tags: - tower - awx diff --git a/roles/tower/tasks/initialize.yml b/roles/tower/tasks/initialize.yml index d4ff0983..0658ae5d 100644 --- a/roles/tower/tasks/initialize.yml +++ b/roles/tower/tasks/initialize.yml @@ -7,7 +7,6 @@ exit(0 if nsu > 0 else 1)' | awx-manage shell" ignore_errors: true - changed_when: false register: users_result changed_when: users_result.rc > 0 @@ -20,7 +19,7 @@ when: users_result.rc > 0 no_log: true -- name: Create preload data if necessary. +- name: Create preload data if necessary. # noqa 305 shell: >- kubectl exec -n {{ meta.namespace }} {{ tower_pod_name }} -- bash -c "awx-manage create_preload_data" diff --git a/roles/tower/tasks/main.yml b/roles/tower/tasks/main.yml index 45819ef8..8368b390 100644 --- a/roles/tower/tasks/main.yml +++ b/roles/tower/tasks/main.yml @@ -44,7 +44,7 @@ register: database_check when: k8s_defs_result is not changed -- name: Migrate the database if the K8s resources were updated. +- name: Migrate the database if the K8s resources were updated. # noqa 305 shell: >- kubectl exec -n {{ meta.namespace }} {{ tower_pod_name }} -- bash -c "awx-manage migrate --noinput"