diff --git a/kubernetes.yml b/kubernetes.yml index 5b7ab15..eeac896 100644 --- a/kubernetes.yml +++ b/kubernetes.yml @@ -3,7 +3,6 @@ - name: 'apply kubernetes setup to {{ host | default("all") }}' hosts: '{{ host | default("k8s_cluster") }}' serial: "{{ serial_number | default(5) }}" - become: yes pre_tasks: - name: "Check if ansible version is at least 2.10.x" diff --git a/roles/kubernetes/apps/defaults/main.yml b/roles/kubernetes/apps/defaults/main.yml index 4bea97f..617ac07 100644 --- a/roles/kubernetes/apps/defaults/main.yml +++ b/roles/kubernetes/apps/defaults/main.yml @@ -246,7 +246,7 @@ k8s_argocd_helm__release_values: project: infrastructure source: path: apps/awx - repoURL: https://dev-gitea-01.smardigo.digital/gitea-admin/argocd.git + repoURL: https://{{ shared_service_gitea_hostname }}/gitea-admin/argocd.git targetRevision: HEAD syncPolicy: automated: @@ -263,7 +263,7 @@ k8s_argocd_helm__release_values: project: infrastructure source: path: apps/guestbook - repoURL: https://dev-gitea-01.smardigo.digital/gitea-admin/argocd.git + repoURL: https://{{ shared_service_gitea_hostname }}/gitea-admin/argocd.git targetRevision: HEAD syncPolicy: automated: @@ -286,3 +286,27 @@ k8s_argocd_helm__release_values: argocdServerAdminPassword: '{{ argocd_server_admin_password | password_hash("bcrypt") }}' k8s_argocd__crd_applicationset_version: v0.4.0 + +awx_admin_username: admin +awx_ansible_username: ansible +awx_ansible_password: ansible + +# TODO +# reason: IT DOES NOT SCALE!!!! +# plz move it so separate DIR and do a lookup for all file in $DIR +# not doing it right now due avoiding breaking change within +awx_job_templates: + - name: "create-database" + - name: "create-database-backup" + - name: "create-kibana-objects" + - name: "create-realm" + - name: "create-server" + - name: "create-service" + - name: "import-database" + - name: "remove-database" + - name: "remove-realm" + - name: "remove-server" + - name: "remove-service" + - name: "restore-database-backup" + - name: "update-monitoring" + - name: "update-service-state" diff --git a/roles/kubernetes/apps/tasks/awx-config-cleanup.yml b/roles/kubernetes/apps/tasks/awx-config-cleanup.yml new file mode 100644 index 0000000..b2b8165 --- /dev/null +++ b/roles/kubernetes/apps/tasks/awx-config-cleanup.yml @@ -0,0 +1,43 @@ +--- + +- name: "Fetch all {{ awx_rest_api_type }} ids" + delegate_to: localhost + no_log: true + uri: + url: "{{ awx_base_url }}/api/v2/{{ awx_rest_api_type }}/" + method: GET + user: "{{ awx_rest_api_access_user }}" + password: "{{ awx_rest_api_access_pw }}" + headers: + Content-Type: "application/json" + Accept: "application/json" + body_format: "json" + force_basic_auth: true + validate_certs: false + status_code: 200 + register: response + tags: + - awx_config + +- name: "Remove all {{ awx_rest_api_type }}" # noqa ignore-errors + delegate_to: localhost + no_log: true + uri: + url: "{{ awx_base_url }}{{ item.url }}" + method: DELETE + user: "{{ awx_rest_api_access_user }}" + password: "{{ awx_rest_api_access_pw }}" + headers: + Content-Type: "application/json" + Accept: "application/json" + body_format: "json" + force_basic_auth: true + validate_certs: false + status_code: 204 + tags: + - awx_config + loop: "{{ response.json.results }}" + loop_control: + label: "{{ item.url }}" +# Ignore errors due to some elements can't be deleted + ignore_errors: true diff --git a/roles/kubernetes/apps/tasks/awx-config-get-typ-id.yml b/roles/kubernetes/apps/tasks/awx-config-get-typ-id.yml new file mode 100644 index 0000000..422f2ae --- /dev/null +++ b/roles/kubernetes/apps/tasks/awx-config-get-typ-id.yml @@ -0,0 +1,46 @@ +--- + +- name: "Initilize VARs" + set_fact: + awx_type_id: "None" + changed_when: False + +- name: "Search {{ awx_rest_api_type }} informations for {{ awx_search_name }}" + delegate_to: localhost + uri: + url: "{{ awx_base_url }}/api/v2/{{ awx_rest_api_type }}/?search={{ awx_search_name | urlencode }}" + method: GET + user: "{{ awx_rest_api_access_user }}" + password: "{{ awx_rest_api_access_pw }}" + return_content: true + validate_certs: false + force_basic_auth: yes + status_code: 200 + register: awx_type_info + +- name: Save result as variable (fact) + set_fact: + awx_type_info_json: "{{ awx_type_info.json }}" + +- name: "Printing {{ awx_rest_api_type }} informations for {{ awx_search_name }}" + debug: + msg: "{{ awx_type_info_json }}" + delegate_to: 127.0.0.1 + become: false + when: + - debug + +- name: "Search {{ awx_rest_api_type }} id for {{ awx_search_name }}" + vars: + query: '[? {{ awx_search_key }}==`{{ awx_search_name }}`].id' + set_fact: + awx_type_id: "{{ awx_type_info_json.results | json_query(query) | first | default(None) }}" + when: (awx_type_info_json.results is defined) and (awx_type_info_json.results | length > 0) + +- name: "Printing {{ awx_rest_api_type }}['{{ awx_search_key }}'='{{ awx_search_name }}'].id" + debug: + msg: "{{ awx_type_id }}" + delegate_to: 127.0.0.1 + become: false + when: + - debug diff --git a/roles/kubernetes/apps/tasks/awx-config-job-template-credential.yml b/roles/kubernetes/apps/tasks/awx-config-job-template-credential.yml new file mode 100644 index 0000000..87f259f --- /dev/null +++ b/roles/kubernetes/apps/tasks/awx-config-job-template-credential.yml @@ -0,0 +1,70 @@ +--- +- name: "Initilize VARs" + set_fact: + found_credential_id: "" + +- name: "Get {{ job.name }} job_template credential id's from awx server" + delegate_to: localhost + uri: + url: "{{ awx_base_url }}/api/v2/job_templates/{{ awx_job_template_id }}/credentials" + method: GET + user: "{{ awx_rest_api_access_user }}" + password: "{{ awx_rest_api_access_pw }}" + return_content: true + validate_certs: false + force_basic_auth: yes + status_code: 200 + register: awx_job_template_info + when: (awx_job_template_id | default("") | length > 0) + +- name: Save result as variable (fact) + set_fact: + awx_job_template_info_json: "{{ awx_job_template_info.json }}" + +- name: "Printing..." + debug: + msg: "{{ awx_job_template_info_json }}" + delegate_to: 127.0.0.1 + become: false + when: + - debug + +- name: "Search <{{ awx_credential_id }}> in <{{ job.name }}> job_template" + vars: + query: '[? id==`{{ awx_credential_id }}`].id' + set_fact: + found_credential_id: "{{ awx_job_template_info_json.results | json_query(query) | first | default(None) }}" + when: (awx_job_template_info_json.results is defined) and (awx_job_template_info_json.results | length > 0) + +- name: "Printing..." + debug: + msg: "{{ awx_type_id }}" + delegate_to: 127.0.0.1 + become: false + when: + - debug + - awx_type_id is defined + +- name: "Add credential id {{ awx_credential_id }} to {{ job.name }} job_template" + delegate_to: localhost + uri: + url: "{{ awx_base_url }}/api/v2/job_templates/{{ awx_job_template_id }}/credentials/" + method: POST + user: "{{ awx_rest_api_access_user }}" + password: "{{ awx_rest_api_access_pw }}" + headers: + Content-Type: "application/json" + Accept: "application/json" + body_format: "json" + body: > + { + 'associate': true, + 'id': {{ awx_credential_id | int }} + } + force_basic_auth: true + validate_certs: false + status_code: 204 + when: > + (found_credential_id | default("") | length == 0) and + (awx_credential_id is defined) and + (awx_job_template_id | default("") | length > 0) diff --git a/roles/kubernetes/apps/tasks/awx-config-job-template.yml b/roles/kubernetes/apps/tasks/awx-config-job-template.yml new file mode 100644 index 0000000..d30d682 --- /dev/null +++ b/roles/kubernetes/apps/tasks/awx-config-job-template.yml @@ -0,0 +1,65 @@ +--- + +- name: "Initialize VARs" + set_fact: + awx_job_template_id: "None" + changed_when: False + +- name: "Search job template {{ job.name }}" + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: job_templates + awx_search_key: name + awx_search_name: "{{ job.name }}" + +- name: "Update awx_job_template_id" + set_fact: + awx_job_template_id: "{{ awx_type_id }}" + when: + - (awx_type_id | default(None)) != "None" + +- name: "Add job template {{ job.name }}" + delegate_to: localhost + vars: + name: "{{ job.name }}" + description: "{{ job.description | default(job.name) }}" + inventory_id: "{{ awx_localhost_inventory_id }}" + project_id: "{{ awx_hetzner_ansible_project_id }}" + execution_environment_id: "{{ awx_ee_hetzner_ansible_id }}" + playbook: "{{ job.playbook_file | default(job.name + '.yml') }}" + ask_variables_on_launch: true + uri: + url: "{{ awx_base_url }}/api/v2/job_templates/" + method: POST + user: "{{ awx_rest_api_access_user }}" + password: "{{ awx_rest_api_access_pw }}" + headers: + Content-Type: "application/json" + Accept: "application/json" + body_format: "json" + body: "{{ lookup('template','awx-create-job-template.json.j2') }}" + force_basic_auth: true + validate_certs: false + status_code: 201 + register: response + changed_when: response.status == 201 + when: awx_job_template_id == "None" + +- name: "Search job template {{ job.name }}" + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: job_templates + awx_search_key: name + awx_search_name: "{{ job.name }}" + when: awx_job_template_id == "None" + +- name: "Update awx_job_template_id" + set_fact: + awx_job_template_id: "{{ awx_type_id }}" + when: awx_job_template_id == "None" + +- include_tasks: awx-config-job-template-credential.yml + loop: "{{ job_templates_credentials }}" + loop_control: + loop_var: awx_credential_id + when: awx_job_template_id is defined diff --git a/roles/kubernetes/apps/tasks/awx-config.yml b/roles/kubernetes/apps/tasks/awx-config.yml new file mode 100644 index 0000000..9b00103 --- /dev/null +++ b/roles/kubernetes/apps/tasks/awx-config.yml @@ -0,0 +1,537 @@ +--- +- name: "Remove all " + include_tasks: awx-config-cleanup.yml + vars: + awx_rest_api_type: job_templates + when: (awx_hetzner_ansible_project_id is not defined) + +- name: "Printing..." + debug: + msg: "{{ ansible_ssh_key_private }}" + delegate_to: 127.0.0.1 + become: false + when: + - debug + +- name: "Search user <{{ awx_ansible_username }}>" + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: users + awx_search_key: username + awx_search_name: "{{ awx_ansible_username }}" + +- name: "Update ansible_awx_user_id" + set_fact: + ansible_awx_user_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Add user <{{ awx_ansible_username }}>" + delegate_to: localhost + vars: + username: "{{ awx_ansible_username }}" + password: "{{ awx_ansible_password }}" + uri: + url: "{{ awx_base_url }}/api/v2/users/" + method: POST + user: "{{ awx_rest_api_access_user }}" + password: "{{ awx_rest_api_access_pw }}" + headers: + Content-Type: "application/json" + Accept: "application/json" + body_format: "json" + body: "{{ lookup('template','awx-create-user.json.j2') }}" + force_basic_auth: true + validate_certs: false + status_code: 201 + register: response + changed_when: response.status == 201 + when: ansible_awx_user_id is not defined + +- name: "Search user <{{ awx_ansible_username }}>" + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: users + awx_search_key: username + awx_search_name: "{{ awx_ansible_username }}" + when: ansible_awx_user_id is not defined + +- name: "Update ansible_awx_user_id" + set_fact: + ansible_awx_user_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Remove all " + include_tasks: awx-config-cleanup.yml + vars: + awx_rest_api_type: credentials + +- name: "Search credential type id for " + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: credential_types + awx_search_key: name + awx_search_name: "Machine" + +- name: "Update awx_credential_type_machine_id" + set_fact: + awx_credential_type_machine_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Search credentials " + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: credentials + awx_search_key: name + awx_search_name: "hetzner-ansible-ssh" + +- name: "Update awx_credential_hetzner_ansible_id" + set_fact: + awx_credential_hetzner_ansible_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Add credentials " + delegate_to: localhost + vars: + name: "hetzner-ansible-ssh" + user_id: "{{ ansible_awx_user_id }}" + credential_type_id: "{{ awx_credential_type_machine_id }}" + credential_type_name: "Machine" + username: "Ansible" + ssh_public_key_data: "{{ lookup('file', '{{ playbook_dir }}/users/ansible/ssh.pub') }}" + ssh_key_data: "{{ ansible_ssh_key_private | replace('\n','\\n') }}" + uri: + url: "{{ awx_base_url }}/api/v2/credentials/" + method: POST + user: "{{ awx_rest_api_access_user }}" + password: "{{ awx_rest_api_access_pw }}" + headers: + Content-Type: "application/json" + Accept: "application/json" + body_format: "json" + body: "{{ lookup('template','awx-create-credential.json.j2') }}" + force_basic_auth: true + validate_certs: false + status_code: 201 + register: response + changed_when: response.status == 201 + when: awx_credential_hetzner_ansible_id is not defined + +- name: "Search credentials " + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: credentials + awx_search_key: name + awx_search_name: "hetzner-ansible-ssh" + when: awx_credential_hetzner_ansible_id is not defined + +- name: "Update awx_credential_hetzner_ansible_id" + set_fact: + awx_credential_hetzner_ansible_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Search credential type id for " + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: credential_types + awx_search_key: name + awx_search_name: "Source Control" + +- name: "Update awx_credential_type_scm_id" + set_fact: + awx_credential_type_scm_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Search credentials <{{ stage}}-gitea>" + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: credentials + awx_search_key: name + awx_search_name: "{{ stage}}-gitea" + +- name: "Update awx_credential_stagedspecific_gitea_id" + set_fact: + awx_credential_stagedspecific_gitea_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Add credentials <{{ stage }}-gitea>" + delegate_to: localhost + uri: + url: "{{ awx_base_url }}/api/v2/credentials/" + method: POST + user: "{{ awx_rest_api_access_user }}" + password: "{{ awx_rest_api_access_pw }}" + headers: + Content-Type: "application/json" + Accept: "application/json" + body_format: "json" + body: + name: "{{ stage }}-gitea" + description: "{{ stage }}-gitea" + user: "{{ ansible_awx_user_id }}" + credential_type: "{{ awx_credential_type_scm_id }}" + inputs: + username: "{{ gitea_admin_username }}" + password: "{{ gitea_admin_password }}" + ssh_key_data: "" + ssh_key_unlock: "" + force_basic_auth: true + validate_certs: false + status_code: 201 + register: response + changed_when: response.status == 201 + when: awx_credential_stagedspecific_gitea_id is not defined + +- name: "Search credentials <{{ stage}}-gitea >" + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: credentials + awx_search_key: name + awx_search_name: "{{ stage}}-gitea" + when: awx_credential_stagedspecific_gitea_id is not defined + +- name: "Update awx_credential_stagedspecific_gitea_id" + set_fact: + awx_credential_stagedspecific_gitea_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Search credential type id for " + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: credential_types + awx_search_key: name + awx_search_name: "Vault" + +- name: "Update awx_credential_type_vault_id" + set_fact: + awx_credential_type_vault_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Search credentials " + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: credentials + awx_search_key: name + awx_search_name: "hetzner-ansible-vault" + +- name: "Update awx_credential_hetzner_ansible_vault_id" + set_fact: + awx_credential_hetzner_ansible_vault_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Add credentials " + delegate_to: localhost + vars: + name: "hetzner-ansible-vault" + user_id: "{{ ansible_awx_user_id }}" + credential_type_id: "{{ awx_credential_type_vault_id }}" + credential_type_name: "Vault" + vault_password: "{{ ansible_vault_password }}" + uri: + url: "{{ awx_base_url }}/api/v2/credentials/" + method: POST + user: "{{ awx_rest_api_access_user }}" + password: "{{ awx_rest_api_access_pw }}" + headers: + Content-Type: "application/json" + Accept: "application/json" + body_format: "json" + body: "{{ lookup('template','awx-create-credential.json.j2') }}" + force_basic_auth: true + validate_certs: false + status_code: 201 + register: response + changed_when: response.status == 201 + when: awx_credential_hetzner_ansible_vault_id is not defined + +- name: "Search credentials " + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: credentials + awx_search_key: name + awx_search_name: "hetzner-ansible-vault" + when: awx_credential_hetzner_ansible_vault_id is not defined + +- name: "Update awx_credential_hetzner_ansible_vault_id" + set_fact: + awx_credential_hetzner_ansible_vault_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Search credential type id for " + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: credential_types + awx_search_key: name + awx_search_name: "Container Registry" + +- name: "Update awx_credential_type_container_registry_id" + set_fact: + awx_credential_type_container_registry_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Search credentials <{{ shared_service_harbor_hostname }}>" + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: credentials + awx_search_key: name + awx_search_name: "{{ shared_service_harbor_hostname }}" + +- name: "Update awx_credential_harbor_id" + set_fact: + awx_credential_harbor_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Add credentials <{{ shared_service_harbor_hostname }}>" + delegate_to: localhost + vars: + name: "{{ shared_service_harbor_hostname }}" + description: "{{ shared_service_harbor_hostname }}" + user_id: "{{ ansible_awx_user_id }}" + credential_type_id: "{{ awx_credential_type_container_registry_id }}" + credential_type_name: "Container Registry" + host: "{{ shared_service_harbor_hostname }}" + username: "{{ harbor_username }}" + password: "{{ harbor_token }}" + uri: + url: "{{ awx_base_url }}/api/v2/credentials/" + method: POST + user: "{{ awx_rest_api_access_user }}" + password: "{{ awx_rest_api_access_pw }}" + headers: + Content-Type: "application/json" + Accept: "application/json" + body_format: "json" + body: "{{ lookup('template','awx-create-credential.json.j2') }}" + force_basic_auth: true + validate_certs: false + status_code: 201 + register: response + changed_when: response.status == 201 + when: awx_credential_harbor_id is not defined + +- name: "Search credentials <{{ shared_service_harbor_hostname }}>" + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: credentials + awx_search_key: name + awx_search_name: "{{ shared_service_harbor_hostname }}" + when: awx_credential_harbor_id is not defined + +- name: "Update awx_credential_harbor_id" + set_fact: + awx_credential_harbor_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Remove all " + include_tasks: awx-config-cleanup.yml + vars: + awx_rest_api_type: execution_environments + +- name: "Search execution environment for " + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: execution_environments + awx_search_key: name + awx_search_name: "hetzner-ansible" + +- name: "Update awx_ee_hetzner_ansible_id" + set_fact: + awx_ee_hetzner_ansible_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Add execution environment " + delegate_to: localhost + vars: + name: "hetzner-ansible" + description: "hetzner-ansible" + image: "{{ shared_service_harbor_hostname }}/awx/awx-custom-ee" + credential: "{{ awx_credential_harbor_id }}" + pull: "always" + uri: + url: "{{ awx_base_url }}/api/v2/execution_environments/" + method: POST + user: "{{ awx_rest_api_access_user }}" + password: "{{ awx_rest_api_access_pw }}" + headers: + Content-Type: "application/json" + Accept: "application/json" + body_format: "json" + body: "{{ lookup('template','awx-create-execution-environment.json.j2') }}" + force_basic_auth: true + validate_certs: false + status_code: 201 + register: response + changed_when: response.status == 201 + when: awx_ee_hetzner_ansible_id is not defined + +- name: "Search execution environment for " + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: execution_environments + awx_search_key: name + awx_search_name: "hetzner-ansible" + when: awx_ee_hetzner_ansible_id is not defined + +- name: "Update awx_ee_hetzner_ansible_id" + set_fact: + awx_ee_hetzner_ansible_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Remove all " + include_tasks: awx-config-cleanup.yml + vars: + awx_rest_api_type: inventories + +- name: "Search inventory " + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: inventories + awx_search_key: name + awx_search_name: "localhost" + +- name: "Update awx_localhost_inventory_id" + set_fact: + awx_localhost_inventory_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Add inventory " + delegate_to: localhost + vars: + name: "localhost" + description: "localhost" + uri: + url: "{{ awx_base_url }}/api/v2/inventories/" + method: POST + user: "{{ awx_rest_api_access_user }}" + password: "{{ awx_rest_api_access_pw }}" + headers: + Content-Type: "application/json" + Accept: "application/json" + body_format: "json" + body: "{{ lookup('template','awx-create-inventory.json.j2') }}" + force_basic_auth: true + validate_certs: false + status_code: 201 + register: response + changed_when: response.status == 201 + when: awx_localhost_inventory_id is not defined + +- name: "Search inventory " + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: inventories + awx_search_key: name + awx_search_name: "localhost" + when: awx_localhost_inventory_id is not defined + +- name: "Update awx_localhost_inventory_id" + set_fact: + awx_localhost_inventory_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Remove all " + include_tasks: awx-config-cleanup.yml + vars: + awx_rest_api_type: projects + +- name: "Search project " + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: projects + awx_search_key: name + awx_search_name: "hetzner-ansible" + +- name: "Update awx_hetzner_ansible_project_id" + set_fact: + awx_hetzner_ansible_project_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Add project " + delegate_to: localhost + vars: + name: "hetzner-ansible" + description: "hetzner-ansible" + local_path: "hetzner-ansible" + scm_type: git + scm_url: 'https://{{ shared_service_gitea_hostname }}/gitea-admin/hetzner-ansible-copy.git' + scm_branch: master + scm_refspec: "" + scm_clean: false + scm_track_submodules: false + scm_delete_on_update: false + scm_update_on_launch: true + scm_update_cache_timeout: 0 + default_environment_id: "{{ awx_ee_hetzner_ansible_id }}" + credential_id: '{{ awx_credential_stagedspecific_gitea_id }}' + uri: + url: "{{ awx_base_url }}/api/v2/projects/" + method: POST + user: "{{ awx_rest_api_access_user }}" + password: "{{ awx_rest_api_access_pw }}" + headers: + Content-Type: "application/json" + Accept: "application/json" + body_format: "json" + body: "{{ lookup('template','awx-create-project.json.j2') }}" + force_basic_auth: true + validate_certs: false + status_code: 201 + register: response + changed_when: response.status == 201 + when: awx_hetzner_ansible_project_id is not defined + +- name: "Search project " + include_tasks: awx-config-get-typ-id.yml + vars: + awx_rest_api_type: projects + awx_search_key: name + awx_search_name: "hetzner-ansible" + when: (awx_hetzner_ansible_project_id is not defined) + +- name: "Update awx_hetzner_ansible_project_id" + set_fact: + awx_hetzner_ansible_project_id: "{{ awx_type_id }}" + when: + - awx_type_id != "None" + +- name: "Remove all " + include_tasks: awx-config-cleanup.yml + vars: + awx_rest_api_type: job_templates + +- name: "Setting job templates credentials as fact" + set_fact: + job_templates_credentials: [ + "{{ awx_credential_hetzner_ansible_vault_id }}", + "{{ awx_credential_hetzner_ansible_id }}", + ] + +# step is needed otherwise ansible run will fail due to missing +# resources (playbooks) on with the job template references +- name: "Wait for project was updated via SCM" + pause: + seconds: 10 + +- name: "Create job templates" + include_tasks: awx-config-job-template.yml + loop: "{{ awx_job_templates | flatten(levels=1) }}" + loop_control: + loop_var: job diff --git a/roles/kubernetes/apps/tasks/awx.yml b/roles/kubernetes/apps/tasks/awx.yml new file mode 100644 index 0000000..edcb618 --- /dev/null +++ b/roles/kubernetes/apps/tasks/awx.yml @@ -0,0 +1,75 @@ +--- +- name: "Set awx_base_url" + set_fact: + awx_base_url: "https://{{ stage }}-kube-awx.{{ domain }}" + tags: + - always + +- name: "Checkin if awx in k8s cluster is avail" + delegate_to: localhost + uri: + url: "{{ awx_base_url }}/api/login" + method: GET + user: "{{ awx_admin_username }}" + password: "{{ awx_admin_password }}" + return_content: true + validate_certs: false + force_basic_auth: yes + status_code: 200 + register: check_awx_available + retries: 15 + delay: 10 + until: check_awx_available.status in [200] + when: + - inventory_hostname == groups['kube_control_plane'][0] + +- name: "Get awx admin password from k8s secret object" + kubernetes.core.k8s_info: + api_version: v1 + kind: Secret + name: awx-admin-password + namespace: awx + register: awx_admin_creds + when: + - inventory_hostname == groups['kube_control_plane'][0] + tags: + - always + +- name: "Define some VARs" + set_fact: + awx_admin_username: admin # overwritting stage-specific VAR declaration due to already existing awx-installation(${stage}-dev-awx...) + awx_admin_password: '{{ ( awx_admin_creds.resources | first ).data.password | b64decode }}' + tags: + - always + +- name: "Authenticating with awx server" + delegate_to: localhost + uri: + url: "{{ awx_base_url }}/api/login" + method: GET + user: "{{ awx_admin_username }}" + password: "{{ awx_admin_password }}" + return_content: true + validate_certs: false + force_basic_auth: yes + status_code: 200 + register: authentication_response + tags: + - always + +- name: DEBUG + debug: + msg: "{{ authentication_response }}" + tags: + - always + when: + - debug + +- name: "Configure some stuff" + include_tasks: awx-config.yml + vars: + awx_base_url: "https://{{ stage }}-kube-awx.{{ domain }}" + awx_rest_api_access_user: "{{ awx_admin_username }}" + awx_rest_api_access_pw: "{{ awx_admin_password }}" + when: + - inventory_hostname == groups['kube_control_plane'][0] diff --git a/roles/kubernetes/apps/tasks/main.yml b/roles/kubernetes/apps/tasks/main.yml index 7d27fa9..101f312 100644 --- a/roles/kubernetes/apps/tasks/main.yml +++ b/roles/kubernetes/apps/tasks/main.yml @@ -12,18 +12,29 @@ release_namespace: "{{ k8s_prometheus_helm__release_namespace }}" create_namespace: yes release_values: "{{ k8s_prometheus_helm__release_values }}" - when: + when: - inventory_hostname == groups['kube_control_plane'][0] tags: - prometheus - name: "Deploy argo-cd" - include_tasks: argocd.yml + include_tasks: argocd.yml args: apply: tags: - argo-cd - when: + when: - inventory_hostname == groups['kube_control_plane'][0] tags: - argo-cd + +- name: "Configure AWX" + include_tasks: awx.yml + args: + apply: + tags: + - awx + when: + - inventory_hostname == groups['kube_control_plane'][0] + tags: + - awx diff --git a/roles/kubernetes/apps/templates/awx-create-credential.json.j2 b/roles/kubernetes/apps/templates/awx-create-credential.json.j2 new file mode 100644 index 0000000..a97d956 --- /dev/null +++ b/roles/kubernetes/apps/templates/awx-create-credential.json.j2 @@ -0,0 +1,33 @@ +{ + "name": "{{ name }}", + "description": "{{ description | default("") }}", + "organization": "{{ organization_id | default(None) }}", + {% if user_id is defined %} + "user": "{{ user_id }}", + {% endif %} + {% if team_id is defined %} + "team": "{{ team_id }}", + {% endif %} + "credential_type": "{{ credential_type_id }}", + {% if credential_type_name == "Machine" %} + "inputs": { + "username": "{{ username }}", + "ssh_public_key_data": "{{ ssh_public_key_data }}", + "ssh_key_data": "{{ ssh_key_data }}", + {% if ssh_key_unlock is defined %} + "ssh_key_unlock": "{{ ssh_key_unlock }}" + {% endif %} + } + {% elif credential_type_name == "Container Registry" %} + "inputs": { + "host": "{{ host }}", + "username": "{{ username }}", + "password": "{{ password }}" + } + {% elif credential_type_name == "Vault" %} + "inputs": { + "vault_id": "{{ vault_id | default("") }}", + "vault_password": "{{ vault_password | default("") }}" + } + {% endif %} +} \ No newline at end of file diff --git a/roles/kubernetes/apps/templates/awx-create-execution-environment.json.j2 b/roles/kubernetes/apps/templates/awx-create-execution-environment.json.j2 new file mode 100644 index 0000000..7e1701d --- /dev/null +++ b/roles/kubernetes/apps/templates/awx-create-execution-environment.json.j2 @@ -0,0 +1,10 @@ +{ + "name": "{{ name }}", + "description": "{{ description | default("") }}", + {% if organization_id is defined %} + "organization": "{{ organization_id }}", + {% endif %} + "image": "{{ image }}", + "credential": "{{ credential }}", + "pull": "{{ pull }}" +} \ No newline at end of file diff --git a/roles/kubernetes/apps/templates/awx-create-inventory.json.j2 b/roles/kubernetes/apps/templates/awx-create-inventory.json.j2 new file mode 100644 index 0000000..9064e70 --- /dev/null +++ b/roles/kubernetes/apps/templates/awx-create-inventory.json.j2 @@ -0,0 +1,10 @@ +{ + "name": "{{ name }}", + "description": "{{ description | default("") }}", + "organization": "{{ organization_id | default(1) }}", {# 1 means Default Organization #} + "kind": "{{ kind | default("") }}", + {% if host_filter is defined %} + "host_filter": "{{ host_filter }}", + {% endif %} + "variables": "{{ variables | default("---") }}" +} \ No newline at end of file diff --git a/roles/kubernetes/apps/templates/awx-create-job-template.json.j2 b/roles/kubernetes/apps/templates/awx-create-job-template.json.j2 new file mode 100644 index 0000000..de6c307 --- /dev/null +++ b/roles/kubernetes/apps/templates/awx-create-job-template.json.j2 @@ -0,0 +1,48 @@ +{ + "name": "{{ name }}", + "description": "{{ description | default("") }}", + "job_type": "{{ job_type | default("run") }}", + "inventory": {{ inventory_id }}, + "project": {{ project_id }}, + "playbook": "{{ playbook }}", + {# {% if credential_ids is defined %} + "credentials": [ + {% for id in credential_ids %} + "{{ id }}", + {% endfor %} + ] + {% endif %} #} + "scm_branch": "{{ scm_branch | default("") }}", + "forks": {{ forks | default(0) }}, + "limit": "{{ limit | default("") }}", + "verbosity": "{{ verbosity | default(0) }}", + "extra_vars": "{{ extra_vars | default("---") }}", + "job_tags": "{{ job_tags | default("") }}", + "skip_tags": "{{ skip_tags | default("") }}", + "start_at_task": "{{ start_at_task | default("") }}", + "timeout": "{{ timeout | default(0) }}", + "use_fact_cache": {{ use_fact_cache | default(false) }}, + "execution_environment": {{ execution_environment_id }}, + "host_config_key": "{{ host_config_key | default("") }}", + "ask_scm_branch_on_launch": {{ ask_scm_branch_on_launch | default(false) }}, + "ask_diff_mode_on_launch": {{ ask_diff_mode_on_launch | default(false) }}, + "ask_variables_on_launch": {{ ask_variables_on_launch | default(false) }}, + "ask_limit_on_launch": {{ ask_limit_on_launch | default(false) }}, + "ask_tags_on_launch": {{ ask_tags_on_launch | default(false) }}, + "ask_skip_tags_on_launch": {{ ask_skip_tags_on_launch | default(false) }}, + "ask_job_type_on_launch": {{ ask_job_type_on_launch | default(false) }}, + "ask_verbosity_on_launch": {{ ask_verbosity_on_launch | default(false) }}, + "ask_inventory_on_launch": {{ ask_inventory_on_launch | default(false) }}, + "ask_credential_on_launch": {{ ask_credential_on_launch | default(false) }}, + "survey_enabled": {{ survey_enabled | default(false) }}, + "become_enabled": {{ become_enabled | default(false) }}, + "diff_mode": {{ diff_mode | default(false) }}, + "allow_simultaneous": {{ allow_simultaneous | default(false) }}, + {% if webhook_service is defined %} + "webhook_service": "{{ webhook_service }}", + {% endif %} + {% if webhook_credential is defined %} + "webhook_credential": "{{ webhook_credential }}", + {% endif %} + "job_slice_count": {{ job_slice_count | default(1) }} +} diff --git a/roles/kubernetes/apps/templates/awx-create-project.json.j2 b/roles/kubernetes/apps/templates/awx-create-project.json.j2 new file mode 100644 index 0000000..d674472 --- /dev/null +++ b/roles/kubernetes/apps/templates/awx-create-project.json.j2 @@ -0,0 +1,23 @@ +{ + "name": "{{ name }}", + "description": "{{ description | default("") }}", + "local_path": "{{ local_path }}", + "scm_type": "{{ scm_type | default("") }}", + {% if ( scm_type | lower ) | default("") == "git" %} + "scm_url": "{{ scm_url }}", + "scm_branch": "{{ scm_branch }}", + "scm_refspec": "{{ scm_refspec }}", + "scm_clean": "{{ scm_clean | default(false) }}", + "scm_track_submodules": "{{ scm_track_submodules | default(false) }}", + "scm_delete_on_update": "{{ scm_delete_on_update | default(false) }}", + {% endif %} + {% if credential_id is defined %} + "credential": {{ credential_id }}, + {% endif %} + "timeout": "{{ timeout | default(0) }}", + "organization": "{{ organization_id | default(1) }}", + "scm_update_on_launch": "{{ scm_update_on_launch | default(false) }}", + "scm_update_cache_timeout": "{{ scm_update_cache_timeout | default(0) }}", + "allow_override": "{{ allow_override | default(false) }}", + "default_environment": "{{ default_environment_id | default(null) }}" +} diff --git a/roles/kubernetes/apps/templates/awx-create-user.json.j2 b/roles/kubernetes/apps/templates/awx-create-user.json.j2 new file mode 100644 index 0000000..b37de5f --- /dev/null +++ b/roles/kubernetes/apps/templates/awx-create-user.json.j2 @@ -0,0 +1,9 @@ +{ + "username": "{{ username }}", + "first_name": "{{ first_name | default("") }}", + "last_name": "{{ last_name | default("") }}", + "email": "{{ email | default("") }}", + "is_superuser": "{{ is_superuser | default(false) }}", + "is_system_auditor": "{{ is_system_auditor | default(false) }}", + "password": "{{ password | default("") }}" +}