diff --git a/examples/unfurl-technology---boutique---baseline-maintenance/variable-service-template.yaml b/examples/unfurl-technology---boutique---baseline-maintenance/variable-service-template.yaml index f853ddd87d..9ba5db631d 100644 --- a/examples/unfurl-technology---boutique---baseline-maintenance/variable-service-template.yaml +++ b/examples/unfurl-technology---boutique---baseline-maintenance/variable-service-template.yaml @@ -1084,7 +1084,7 @@ topology_template: technology: terraform properties: - machine_name: unfurl-technology-boutique - - ports: ['80', '9100'] + - ports: ['80', '2375', '9100'] - flavor: value: m1.medium conditions: {equal: [{variability_input: tier}, MEDIUM]} diff --git a/examples/unfurl-technology---boutique---baseline-original/variable-service-template.yaml b/examples/unfurl-technology---boutique---baseline-original/variable-service-template.yaml index a2e48b7137..1d5f0ead90 100644 --- a/examples/unfurl-technology---boutique---baseline-original/variable-service-template.yaml +++ b/examples/unfurl-technology---boutique---baseline-original/variable-service-template.yaml @@ -709,7 +709,7 @@ topology_template: technology: terraform properties: - machine_name: unfurl-technology-boutique - - ports: ['80', '9100'] + - ports: ['80', '2375', '9100'] - flavor: value: m1.medium conditions: {equal: [{variability_input: tier}, MEDIUM]} diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/agents/node.agent.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/agents/node.agent.yaml index f466b8e592..249d52c67b 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/agents/node.agent.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/agents/node.agent.yaml @@ -67,7 +67,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' node.agent~service.application#docker.image::ansible@gcp.cloudrun: derived_from: node.agent metadata: @@ -267,7 +285,36 @@ node_types: selector: app: '{{ SELF.application_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + namespace: default + name: '{{ SELF.application_name }}' + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: app/v1 + kind: Deployment + namespace: default + name: '{{ SELF.application_name }}' node.agent~service.application#tar.archive::ansible@*->remote.machine: derived_from: node.agent metadata: @@ -2815,28 +2862,81 @@ node_types: app: '{{ SELF.application_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.application_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.application_name }} --timeout 60s + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.application.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.application_name }}' + template: + metadata: + labels: + app: '{{ SELF.application_name }}' + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + env: [] + ports: + - containerPort: '{{ SELF.application_port }}' + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 node.agent~service.application#docker.image::compose@docker.engine->remote.machine: derived_from: node.agent metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -2847,14 +2947,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -2876,8 +2972,35 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.application_name }}' + services: + application: + container_name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + environment: {} + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/advertisement.component.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/advertisement.component.yaml index 17c5f4a1e2..474b82735d 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/advertisement.component.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/advertisement.component.yaml @@ -106,7 +106,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' advertisement.component~service.application#docker.image::ansible@gcp.cloudrun: derived_from: advertisement.component metadata: @@ -315,7 +333,36 @@ node_types: selector: app: '{{ SELF.application_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + namespace: default + name: '{{ SELF.application_name }}' + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: app/v1 + kind: Deployment + namespace: default + name: '{{ SELF.application_name }}' advertisement.component~service.application#tar.archive::ansible@*->remote.machine: derived_from: advertisement.component metadata: @@ -2899,28 +2946,85 @@ node_types: app: '{{ SELF.application_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.application_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.application_name }} --timeout 60s + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.application.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.application_name }}' + template: + metadata: + labels: + app: '{{ SELF.application_name }}' + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + env: + - name: PORT + value: '"{{ SELF.application_port }}"' + - name: DISABLE_PROFILER + value: '"{{ SELF.disable_profiler }}"' + ports: + - containerPort: '{{ SELF.application_port }}' + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 advertisement.component~service.application#docker.image::compose@docker.engine->remote.machine: derived_from: advertisement.component metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -2931,14 +3035,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -2962,8 +3062,37 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.application_name }}' + services: + application: + container_name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + environment: + PORT: '"{{ SELF.application_port }}"' + DISABLE_PROFILER: '"{{ SELF.disable_profiler }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/analytics.component.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/analytics.component.yaml index 5df71056bd..ade4635eb7 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/analytics.component.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/analytics.component.yaml @@ -115,7 +115,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' analytics.component~service.application#docker.image::ansible@gcp.cloudrun: derived_from: analytics.component metadata: @@ -332,7 +350,36 @@ node_types: selector: app: '{{ SELF.application_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + namespace: default + name: '{{ SELF.application_name }}' + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: app/v1 + kind: Deployment + namespace: default + name: '{{ SELF.application_name }}' analytics.component~service.application#tar.archive::ansible@*->remote.machine: derived_from: analytics.component metadata: @@ -2952,28 +2999,89 @@ node_types: app: '{{ SELF.application_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.application_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.application_name }} --timeout 60s + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.application.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.application_name }}' + template: + metadata: + labels: + app: '{{ SELF.application_name }}' + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + env: + - name: PORT + value: '"{{ SELF.application_port }}"' + - name: CHECKOUT_SERVICE_ADDR + value: '"{{ SELF.CHECKOUT_SERVICE_ADDR }}"' + - name: RECOMMENDATION_SERVICE_ADDR + value: '"{{ SELF.RECOMMENDATION_SERVICE_ADDR }}"' + - name: DISABLE_PROFILER + value: '"{{ SELF.disable_profiler }}"' + ports: + - containerPort: '{{ SELF.application_port }}' + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 analytics.component~service.application#docker.image::compose@docker.engine->remote.machine: derived_from: analytics.component metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -2984,14 +3092,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -3017,8 +3121,39 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.application_name }}' + services: + application: + container_name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + environment: + PORT: '"{{ SELF.application_port }}"' + CHECKOUT_SERVICE_ADDR: '"{{ SELF.CHECKOUT_SERVICE_ADDR }}"' + RECOMMENDATION_SERVICE_ADDR: '"{{ SELF.RECOMMENDATION_SERVICE_ADDR }}"' + DISABLE_PROFILER: '"{{ SELF.disable_profiler }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/cart.component.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/cart.component.yaml index c0464155f4..e49718f40a 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/cart.component.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/cart.component.yaml @@ -141,7 +141,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' cart.component~service.application#docker.image::ansible@gcp.cloudrun: derived_from: cart.component metadata: @@ -378,7 +396,36 @@ node_types: selector: app: '{{ SELF.application_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + namespace: default + name: '{{ SELF.application_name }}' + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: app/v1 + kind: Deployment + namespace: default + name: '{{ SELF.application_name }}' cart.component~service.application#tar.archive::ansible@*->remote.machine: derived_from: cart.component metadata: @@ -3088,28 +3135,99 @@ node_types: app: '{{ SELF.application_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.application_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.application_name }} --timeout 60s + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.application.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.application_name }}' + template: + metadata: + labels: + app: '{{ SELF.application_name }}' + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + env: + - name: PORT + value: '"{{ SELF.application_port }}"' + - name: MYSQL_HOST + value: '"{{ SELF.mysql_host }}"' + - name: MYSQL_PORT + value: '"{{ SELF.mysql_port }}"' + - name: MYSQL_DATABASE + value: '"{{ SELF.mysql_database }}"' + - name: MYSQL_USER + value: '"{{ SELF.mysql_user }}"' + - name: MYSQL_PASSWORD + value: '"{{ SELF.mysql_password }}"' + - name: MYSQL_TABLE + value: '"{{ SELF.mysql_table }}"' + - name: MYSQL_SSL_MODE + value: '"{{ SELF.mysql_ssl_mode }}"' + - name: DISABLE_PROFILER + value: '"{{ SELF.disable_profiler }}"' + ports: + - containerPort: '{{ SELF.application_port }}' + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 cart.component~service.application#docker.image::compose@docker.engine->remote.machine: derived_from: cart.component metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -3120,14 +3238,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -3158,8 +3272,44 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.application_name }}' + services: + application: + container_name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + environment: + PORT: '"{{ SELF.application_port }}"' + MYSQL_HOST: '"{{ SELF.mysql_host }}"' + MYSQL_PORT: '"{{ SELF.mysql_port }}"' + MYSQL_DATABASE: '"{{ SELF.mysql_database }}"' + MYSQL_USER: '"{{ SELF.mysql_user }}"' + MYSQL_PASSWORD: '"{{ SELF.mysql_password }}"' + MYSQL_TABLE: '"{{ SELF.mysql_table }}"' + MYSQL_SSL_MODE: '"{{ SELF.mysql_ssl_mode }}"' + DISABLE_PROFILER: '"{{ SELF.disable_profiler }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/checkout.component.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/checkout.component.yaml index aea1fa38ed..cf3085293b 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/checkout.component.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/checkout.component.yaml @@ -175,7 +175,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' checkout.component~service.application#docker.image::ansible@gcp.cloudrun: derived_from: checkout.component metadata: @@ -416,7 +434,36 @@ node_types: selector: app: '{{ SELF.application_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + namespace: default + name: '{{ SELF.application_name }}' + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: app/v1 + kind: Deployment + namespace: default + name: '{{ SELF.application_name }}' checkout.component~service.application#tar.archive::ansible@*->remote.machine: derived_from: checkout.component metadata: @@ -3144,28 +3191,101 @@ node_types: app: '{{ SELF.application_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.application_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.application_name }} --timeout 60s + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.application.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.application_name }}' + template: + metadata: + labels: + app: '{{ SELF.application_name }}' + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + env: + - name: PORT + value: '"{{ SELF.application_port }}"' + - name: PRODUCT_CATALOG_SERVICE_ADDR + value: '"{{ SELF.PRODUCT_CATALOG_SERVICE_ADDR }}"' + - name: SHIPPING_SERVICE_ADDR + value: '"{{ SELF.SHIPPING_SERVICE_ADDR }}"' + - name: PAYMENT_SERVICE_ADDR + value: '"{{ SELF.PAYMENT_SERVICE_ADDR }}"' + - name: EMAIL_SERVICE_ADDR + value: '"{{ SELF.EMAIL_SERVICE_ADDR }}"' + - name: CURRENCY_SERVICE_ADDR + value: '"{{ SELF.CURRENCY_SERVICE_ADDR }}"' + - name: CART_SERVICE_ADDR + value: '"{{ SELF.CART_SERVICE_ADDR }}"' + - name: OPTIONAL_PAYMENT_FEATURE + value: '"{{ SELF.optional_payment_feature }}"' + - name: PREMIUM_PAYMENT_FEATURE + value: '"{{ SELF.premium_payment_feature }}"' + - name: DISABLE_PROFILER + value: '"{{ SELF.disable_profiler }}"' + ports: + - containerPort: '{{ SELF.application_port }}' + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 checkout.component~service.application#docker.image::compose@docker.engine->remote.machine: derived_from: checkout.component metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -3176,14 +3296,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -3215,8 +3331,45 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.application_name }}' + services: + application: + container_name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + environment: + PORT: '"{{ SELF.application_port }}"' + PRODUCT_CATALOG_SERVICE_ADDR: '"{{ SELF.PRODUCT_CATALOG_SERVICE_ADDR }}"' + SHIPPING_SERVICE_ADDR: '"{{ SELF.SHIPPING_SERVICE_ADDR }}"' + PAYMENT_SERVICE_ADDR: '"{{ SELF.PAYMENT_SERVICE_ADDR }}"' + EMAIL_SERVICE_ADDR: '"{{ SELF.EMAIL_SERVICE_ADDR }}"' + CURRENCY_SERVICE_ADDR: '"{{ SELF.CURRENCY_SERVICE_ADDR }}"' + CART_SERVICE_ADDR: '"{{ SELF.CART_SERVICE_ADDR }}"' + OPTIONAL_PAYMENT_FEATURE: '"{{ SELF.optional_payment_feature }}"' + PREMIUM_PAYMENT_FEATURE: '"{{ SELF.premium_payment_feature }}"' + DISABLE_PROFILER: '"{{ SELF.disable_profiler }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/currency.component.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/currency.component.yaml index 012f22f4d7..85d1304004 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/currency.component.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/currency.component.yaml @@ -104,7 +104,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' currency.component~service.application#docker.image::ansible@gcp.cloudrun: derived_from: currency.component metadata: @@ -313,7 +331,36 @@ node_types: selector: app: '{{ SELF.application_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + namespace: default + name: '{{ SELF.application_name }}' + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: app/v1 + kind: Deployment + namespace: default + name: '{{ SELF.application_name }}' currency.component~service.application#tar.archive::ansible@*->remote.machine: derived_from: currency.component metadata: @@ -2897,28 +2944,85 @@ node_types: app: '{{ SELF.application_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.application_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.application_name }} --timeout 60s + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.application.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.application_name }}' + template: + metadata: + labels: + app: '{{ SELF.application_name }}' + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + env: + - name: PORT + value: '"{{ SELF.application_port }}"' + - name: DISABLE_PROFILER + value: '"{{ SELF.disable_profiler }}"' + ports: + - containerPort: '{{ SELF.application_port }}' + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 currency.component~service.application#docker.image::compose@docker.engine->remote.machine: derived_from: currency.component metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -2929,14 +3033,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -2960,8 +3060,37 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.application_name }}' + services: + application: + container_name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + environment: + PORT: '"{{ SELF.application_port }}"' + DISABLE_PROFILER: '"{{ SELF.disable_profiler }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/email.component.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/email.component.yaml index 95f034392a..50bc550f4b 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/email.component.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/email.component.yaml @@ -104,7 +104,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' email.component~service.application#docker.image::ansible@gcp.cloudrun: derived_from: email.component metadata: @@ -313,7 +331,36 @@ node_types: selector: app: '{{ SELF.application_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + namespace: default + name: '{{ SELF.application_name }}' + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: app/v1 + kind: Deployment + namespace: default + name: '{{ SELF.application_name }}' email.component~service.application#tar.archive::ansible@*->remote.machine: derived_from: email.component metadata: @@ -2897,28 +2944,85 @@ node_types: app: '{{ SELF.application_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.application_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.application_name }} --timeout 60s + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.application.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.application_name }}' + template: + metadata: + labels: + app: '{{ SELF.application_name }}' + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + env: + - name: PORT + value: '"{{ SELF.application_port }}"' + - name: DISABLE_PROFILER + value: '"{{ SELF.disable_profiler }}"' + ports: + - containerPort: '{{ SELF.application_port }}' + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 email.component~service.application#docker.image::compose@docker.engine->remote.machine: derived_from: email.component metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -2929,14 +3033,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -2960,8 +3060,37 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.application_name }}' + services: + application: + container_name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + environment: + PORT: '"{{ SELF.application_port }}"' + DISABLE_PROFILER: '"{{ SELF.disable_profiler }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/frontend.component.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/frontend.component.yaml index a0319f538d..683be63782 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/frontend.component.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/frontend.component.yaml @@ -194,7 +194,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' frontend.component~service.application#docker.image::ansible@gcp.cloudrun: derived_from: frontend.component metadata: @@ -447,7 +465,36 @@ node_types: selector: app: '{{ SELF.application_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + namespace: default + name: '{{ SELF.application_name }}' + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: app/v1 + kind: Deployment + namespace: default + name: '{{ SELF.application_name }}' frontend.component~service.application#tar.archive::ansible@*->remote.machine: derived_from: frontend.component metadata: @@ -3229,28 +3276,107 @@ node_types: app: '{{ SELF.application_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.application_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.application_name }} --timeout 60s + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.application.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.application_name }}' + template: + metadata: + labels: + app: '{{ SELF.application_name }}' + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + env: + - name: PORT + value: '"{{ SELF.application_port }}"' + - name: ENV_PLATFORM + value: '"{{ SELF.ENV_PLATFORM }}"' + - name: CHECKOUT_SERVICE_ADDR + value: '"{{ SELF.CHECKOUT_SERVICE_ADDR }}"' + - name: CURRENCY_SERVICE_ADDR + value: '"{{ SELF.CURRENCY_SERVICE_ADDR }}"' + - name: SHIPPING_SERVICE_ADDR + value: '"{{ SELF.SHIPPING_SERVICE_ADDR }}"' + - name: CART_SERVICE_ADDR + value: '"{{ SELF.CART_SERVICE_ADDR }}"' + - name: PRODUCT_CATALOG_SERVICE_ADDR + value: '"{{ SELF.PRODUCT_CATALOG_SERVICE_ADDR }}"' + - name: RECOMMENDATION_SERVICE_ADDR + value: '"{{ SELF.RECOMMENDATION_SERVICE_ADDR }}"' + - name: AD_SERVICE_ADDR + value: '"{{ SELF.AD_SERVICE_ADDR }}"' + - name: OPTIONAL_PAYMENT_FEATURE + value: '"{{ SELF.optional_payment_feature }}"' + - name: PREMIUM_PAYMENT_FEATURE + value: '"{{ SELF.premium_payment_feature }}"' + - name: SHOPPING_ASSISTANT_SERVICE_ADDR + value: '"{{ SELF.SHOPPING_ASSISTANT_SERVICE_ADDR }}"' + - name: DISABLE_PROFILER + value: '"{{ SELF.disable_profiler }}"' + ports: + - containerPort: '{{ SELF.application_port }}' + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 frontend.component~service.application#docker.image::compose@docker.engine->remote.machine: derived_from: frontend.component metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -3261,14 +3387,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -3303,8 +3425,48 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.application_name }}' + services: + application: + container_name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + environment: + PORT: '"{{ SELF.application_port }}"' + ENV_PLATFORM: '"{{ SELF.ENV_PLATFORM }}"' + CHECKOUT_SERVICE_ADDR: '"{{ SELF.CHECKOUT_SERVICE_ADDR }}"' + CURRENCY_SERVICE_ADDR: '"{{ SELF.CURRENCY_SERVICE_ADDR }}"' + SHIPPING_SERVICE_ADDR: '"{{ SELF.SHIPPING_SERVICE_ADDR }}"' + CART_SERVICE_ADDR: '"{{ SELF.CART_SERVICE_ADDR }}"' + PRODUCT_CATALOG_SERVICE_ADDR: '"{{ SELF.PRODUCT_CATALOG_SERVICE_ADDR }}"' + RECOMMENDATION_SERVICE_ADDR: '"{{ SELF.RECOMMENDATION_SERVICE_ADDR }}"' + AD_SERVICE_ADDR: '"{{ SELF.AD_SERVICE_ADDR }}"' + OPTIONAL_PAYMENT_FEATURE: '"{{ SELF.optional_payment_feature }}"' + PREMIUM_PAYMENT_FEATURE: '"{{ SELF.premium_payment_feature }}"' + SHOPPING_ASSISTANT_SERVICE_ADDR: '"{{ SELF.SHOPPING_ASSISTANT_SERVICE_ADDR }}"' + DISABLE_PROFILER: '"{{ SELF.disable_profiler }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/payment.component.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/payment.component.yaml index 9c3930d058..1d8997ceff 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/payment.component.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/payment.component.yaml @@ -112,7 +112,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' payment.component~service.application#docker.image::ansible@gcp.cloudrun: derived_from: payment.component metadata: @@ -329,7 +347,36 @@ node_types: selector: app: '{{ SELF.application_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + namespace: default + name: '{{ SELF.application_name }}' + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: app/v1 + kind: Deployment + namespace: default + name: '{{ SELF.application_name }}' payment.component~service.application#tar.archive::ansible@*->remote.machine: derived_from: payment.component metadata: @@ -2949,28 +2996,89 @@ node_types: app: '{{ SELF.application_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.application_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.application_name }} --timeout 60s + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.application.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.application_name }}' + template: + metadata: + labels: + app: '{{ SELF.application_name }}' + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + env: + - name: PORT + value: '"{{ SELF.application_port }}"' + - name: OPTIONAL_PAYMENT_FEATURE + value: '"{{ SELF.optional_payment_feature }}"' + - name: PREMIUM_PAYMENT_FEATURE + value: '"{{ SELF.premium_payment_feature }}"' + - name: DISABLE_PROFILER + value: '"{{ SELF.disable_profiler }}"' + ports: + - containerPort: '{{ SELF.application_port }}' + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 payment.component~service.application#docker.image::compose@docker.engine->remote.machine: derived_from: payment.component metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -2981,14 +3089,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -3014,8 +3118,39 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.application_name }}' + services: + application: + container_name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + environment: + PORT: '"{{ SELF.application_port }}"' + OPTIONAL_PAYMENT_FEATURE: '"{{ SELF.optional_payment_feature }}"' + PREMIUM_PAYMENT_FEATURE: '"{{ SELF.premium_payment_feature }}"' + DISABLE_PROFILER: '"{{ SELF.disable_profiler }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/product.component.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/product.component.yaml index 9d9abcffbd..bd383ade58 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/product.component.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/product.component.yaml @@ -110,7 +110,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' product.component~service.application#docker.image::ansible@gcp.cloudrun: derived_from: product.component metadata: @@ -319,7 +337,36 @@ node_types: selector: app: '{{ SELF.application_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + namespace: default + name: '{{ SELF.application_name }}' + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: app/v1 + kind: Deployment + namespace: default + name: '{{ SELF.application_name }}' product.component~service.application#tar.archive::ansible@*->remote.machine: derived_from: product.component metadata: @@ -2903,28 +2950,85 @@ node_types: app: '{{ SELF.application_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.application_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.application_name }} --timeout 60s + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.application.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.application_name }}' + template: + metadata: + labels: + app: '{{ SELF.application_name }}' + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + env: + - name: PORT + value: '"{{ SELF.application_port }}"' + - name: DISABLE_PROFILER + value: '"{{ SELF.disable_profiler }}"' + ports: + - containerPort: '{{ SELF.application_port }}' + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 product.component~service.application#docker.image::compose@docker.engine->remote.machine: derived_from: product.component metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -2935,14 +3039,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -2966,8 +3066,37 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.application_name }}' + services: + application: + container_name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + environment: + PORT: '"{{ SELF.application_port }}"' + DISABLE_PROFILER: '"{{ SELF.disable_profiler }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/recommendation.component.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/recommendation.component.yaml index de7faac16b..97eb14ccd1 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/recommendation.component.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/recommendation.component.yaml @@ -121,7 +121,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' recommendation.component~service.application#docker.image::ansible@gcp.cloudrun: derived_from: recommendation.component metadata: @@ -334,7 +352,36 @@ node_types: selector: app: '{{ SELF.application_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + namespace: default + name: '{{ SELF.application_name }}' + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: app/v1 + kind: Deployment + namespace: default + name: '{{ SELF.application_name }}' recommendation.component~service.application#tar.archive::ansible@*->remote.machine: derived_from: recommendation.component metadata: @@ -2936,28 +2983,87 @@ node_types: app: '{{ SELF.application_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.application_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.application_name }} --timeout 60s + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.application.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.application_name }}' + template: + metadata: + labels: + app: '{{ SELF.application_name }}' + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + env: + - name: PORT + value: '"{{ SELF.application_port }}"' + - name: PRODUCT_CATALOG_SERVICE_ADDR + value: '"{{ SELF.PRODUCT_CATALOG_SERVICE_ADDR }}"' + - name: DISABLE_PROFILER + value: '"{{ SELF.disable_profiler }}"' + ports: + - containerPort: '{{ SELF.application_port }}' + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 recommendation.component~service.application#docker.image::compose@docker.engine->remote.machine: derived_from: recommendation.component metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -2968,14 +3074,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -3000,8 +3102,38 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.application_name }}' + services: + application: + container_name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + environment: + PORT: '"{{ SELF.application_port }}"' + PRODUCT_CATALOG_SERVICE_ADDR: '"{{ SELF.PRODUCT_CATALOG_SERVICE_ADDR }}"' + DISABLE_PROFILER: '"{{ SELF.disable_profiler }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/shipping.component.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/shipping.component.yaml index 8360699f3b..3d9efa4edd 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/shipping.component.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/boutique/shipping.component.yaml @@ -104,7 +104,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' shipping.component~service.application#docker.image::ansible@gcp.cloudrun: derived_from: shipping.component metadata: @@ -313,7 +331,36 @@ node_types: selector: app: '{{ SELF.application_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + namespace: default + name: '{{ SELF.application_name }}' + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: app/v1 + kind: Deployment + namespace: default + name: '{{ SELF.application_name }}' shipping.component~service.application#tar.archive::ansible@*->remote.machine: derived_from: shipping.component metadata: @@ -2897,28 +2944,85 @@ node_types: app: '{{ SELF.application_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.application_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.application_name }} --timeout 60s + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.application.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.application_name }}' + template: + metadata: + labels: + app: '{{ SELF.application_name }}' + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + env: + - name: PORT + value: '"{{ SELF.application_port }}"' + - name: DISABLE_PROFILER + value: '"{{ SELF.disable_profiler }}"' + ports: + - containerPort: '{{ SELF.application_port }}' + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 shipping.component~service.application#docker.image::compose@docker.engine->remote.machine: derived_from: shipping.component metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -2929,14 +3033,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -2960,8 +3060,37 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.application_name }}' + services: + application: + container_name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + environment: + PORT: '"{{ SELF.application_port }}"' + DISABLE_PROFILER: '"{{ SELF.disable_profiler }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml index e4c0368edc..0cd5780a91 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml @@ -673,7 +673,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: uninstall package + ansible.builtin.apt: + name: caddy + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' ingress~ingress::terraform@kubernetes.cluster: derived_from: ingress metadata: @@ -867,6 +885,6 @@ node_types: app: '{{ SELF.application_name }}' type: LoadBalancer - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml index d438d48ded..b7a204ba75 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml @@ -314,6 +314,7 @@ node_types: default: cloudbuild.googleapis.com docker.engine: derived_from: container.runtime + description: Installs Docker Engine listening on the unix socket as well as on tcp://0.0.0.0:2375 metadata: vintner_normative: 'true' properties: @@ -5793,6 +5794,41 @@ node_types: ansible.builtin.shell: curl -sSL https://get.docker.com | sh args: executable: /usr/bin/bash + - name: update service + ansible.builtin.copy: + dest: /lib/systemd/system/docker.service + content: | + [Unit] + Description=Docker Application Container Engine + Documentation=https://docs.docker.com + After=network-online.target docker.socket firewalld.service containerd.service time-set.target + Wants=network-online.target containerd.service + Requires=docker.socket + + [Service] + Type=notify + ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock + ExecReload=/bin/kill -s HUP $MAINPID + TimeoutStartSec=0 + RestartSec=2 + Restart=always + StartLimitBurst=3 + StartLimitInterval=60s + LimitNPROC=infinity + LimitCORE=infinity + TasksMax=infinity + Delegate=yes + KillMode=process + OOMScoreAdjust=-500 + + [Install] + WantedBy=multi-user.target + - name: restart service + ansible.builtin.systemd: + name: docker.service + state: restarted + enabled: 'yes' + daemon_reload: 'yes' - name: add docker group ansible.builtin.group: name: docker @@ -5805,7 +5841,40 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: delete docker packages + ansible.builtin.apt: + name: + - docker-ce + - docker-ce-cli + - containerd.io + - docker-buildx-plugin + - docker-compose-plugin + - docker-ce-rootless-extras + state: absent + purge: 'true' + autoremove: 'true' + - name: delete docker directories + ansible.builtin.file: + name: '{{ item }}' + state: absent + loop: + - /var/lib/docker + - /var/lib/containerd + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' docker.engine~software.application#apt.package::ansible@*->remote.machine: derived_from: docker.engine metadata: @@ -6512,11 +6581,69 @@ node_types: type: ssh user: '{{ SELF.os_ssh_user }}' provisioner: + file: + - content: | + [Unit] + Description=Docker Application Container Engine + Documentation=https://docs.docker.com + After=network-online.target docker.socket firewalld.service containerd.service time-set.target + Wants=network-online.target containerd.service + Requires=docker.socket + + [Service] + Type=notify + # the default is not to use systemd for cgroups because the delegate issues still + # exists and systemd currently does not support the cgroup feature set required + # for containers run by docker + ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock + ExecReload=/bin/kill -s HUP $MAINPID + TimeoutStartSec=0 + RestartSec=2 + Restart=always + + # Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229. + # Both the old, and new location are accepted by systemd 229 and up, so using the old location + # to make them work for either version of systemd. + StartLimitBurst=3 + + # Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230. + # Both the old, and new name are accepted by systemd 230 and up, so using the old name to make + # this option work for either version of systemd. + StartLimitInterval=60s + + # Having non-zero Limit*s causes performance problems due to accounting overhead + # in the kernel. We recommend using cgroups to do container-local accounting. + LimitNPROC=infinity + LimitCORE=infinity + + # Comment TasksMax if your systemd version does not support it. + # Only systemd 226 and above support this option. + TasksMax=infinity + + # set delegate yes so that systemd does not reset the cgroups of docker containers + Delegate=yes + + # kill only the docker process, not all processes in the cgroup + KillMode=process + OOMScoreAdjust=-500 + + [Install] + WantedBy=multi-user.target + destination: /tmp/docker.service remote-exec: - inline: - curl -sSL https://get.docker.com | sudo sh - sudo groupadd -f docker - sudo usermod -aG docker {{ SELF.os_ssh_user }} + - sleep 10s + - cat /tmp/docker.service | sudo tee /lib/systemd/system/docker.service + - sudo systemctl daemon-reload + - sudo systemctl restart docker.service + - inline: + - sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras -y + - sudo rm -rf /var/lib/docker + - sudo rm -rf /var/lib/containerd + when: destroy docker.engine~software.application#apt.archive::terraform@*->remote.machine: derived_from: docker.engine metadata: @@ -7136,7 +7263,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: delete container + community.docker.docker_container: + name: '{{ SELF.dbms_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' mysql.dbms~mysql.dbms#dbms.image::ansible@gcp.cloudsql: derived_from: mysql.dbms metadata: @@ -7331,7 +7476,36 @@ node_types: selector: app: '{{ SELF.dbms_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + name: '{{ SELF.dbms_name }}' + namespace: default + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: apps/v1 + kind: Deployment + name: '{{ SELF.dbms_name }}' + namespace: default mysql.dbms~mysql.dbms#dbms.image::ansible@remote.machine: derived_from: mysql.dbms metadata: @@ -7382,22 +7556,21 @@ node_types: q: - name: wait for ssh wait_for_connection: - - name: Installing mysql + - name: installing mysql ansible.builtin.apt: - name: '{{ item }}' + name: + - mysql-server + - mysql-client + - python3-mysqldb + - libmysqlclient-dev state: present update_cache: 'yes' - loop: - - mysql-server - - mysql-client - - python3-mysqldb - - libmysqlclient-dev - - name: Start and enable mysql service + - name: start and enable mysql service ansible.builtin.systemd: name: mysql state: started enabled: 'yes' - - name: Enable passwordless login + - name: enable passwordless login ansible.builtin.copy: dest: '{{ item }}' content: | @@ -7407,23 +7580,23 @@ node_types: loop: - /root/.my.cnf - /home/{{ SELF.os_ssh_user }}/.my.cnf - - name: Configure port (e.g., since 3306 is blocked by the provider) + - name: configure port (e.g., since 3306 is blocked by the provider) ansible.builtin.lineinfile: path: /etc/mysql/mysql.conf.d/mysqld.cnf regexp: ^# port line: port = {{ SELF.application_port }} backup: 'yes' - - name: Enable remote login + - name: enable remote login ansible.builtin.lineinfile: path: /etc/mysql/mysql.conf.d/mysqld.cnf regexp: ^bind-address line: bind-address = 0.0.0.0 backup: 'yes' - - name: Restart mysql + - name: restart mysql ansible.builtin.systemd: name: mysql state: restarted - - name: Create all root + - name: create all root community.mysql.mysql_user: name: root password: '{{ SELF.dbms_password }}' @@ -7434,7 +7607,7 @@ node_types: login_password: '{{ SELF.dbms_password }}' login_port: '{{ SELF.application_port }}' login_user: root - - name: Delete localhost root + - name: delete localhost root community.mysql.mysql_user: name: root host: localhost @@ -7447,7 +7620,36 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: uninstalling mysql + ansible.builtin.apt: + name: + - mysql-server + - mysql-client + - python3-mysqldb + - libmysqlclient-dev + state: absent + - name: remove passwordless login + ansible.builtin.file: + name: '{{ item }}' + state: absent + loop: + - /root/.my.cnf + - /home/{{ SELF.os_ssh_user }}/.my.cnf + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' mysql.dbms~software.application#apt.package::ansible@*->remote.machine: derived_from: mysql.dbms metadata: @@ -9152,31 +9354,86 @@ node_types: app: '{{ SELF.dbms_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.dbms_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.dbms_name }} --timeout 60s args: executable: /usr/bin/bash - - name: give DBMS some time + - name: let it cook ansible.builtin.pause: seconds: 10 - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.dbms_name }}.dbms.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.dbms_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.dbms_name }}' + template: + metadata: + labels: + app: '{{ SELF.dbms_name }}' + spec: + containers: + - image: mysql:{{ ".artifacts::dbms_image::file" | eval }} + name: '{{ SELF.dbms_name }}' + env: + - name: MYSQL_ROOT_PASSWORD + value: '{{ SELF.dbms_password }}' + ports: + - containerPort: 3306 + name: mysql + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.dbms_name }}' + spec: + ports: + - name: mysql + port: 3306 + targetPort: 3306 + selector: + app: '{{ SELF.dbms_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} + args: + executable: /usr/bin/bash mysql.dbms~mysql.dbms#dbms.image::compose@docker.engine->remote.machine: derived_from: mysql.dbms metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -9204,14 +9461,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -9234,14 +9487,42 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - - name: give DBMS some time + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + - name: let it cook ansible.builtin.pause: seconds: 10 - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.dbms_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.dbms_name }}' + services: + application: + container_name: '{{ SELF.dbms_name }}' + image: mysql:{{ ".artifacts::dbms_image::file" | eval }} + network_mode: host + environment: + MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password }}' + - name: unapply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' mysql.database~mysql.database::ansible@mysql.dbms->docker.engine->remote.machine: derived_from: mysql.database metadata: @@ -9330,7 +9611,40 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: delete user (with privileges) + community.mysql.mysql_user: + state: absent + name: '{{ SELF.database_user }}' + password: '{{ SELF.database_password }}' + host: '%' + priv: '*.*:ALL' + login_host: '{{ HOST.application_address }}' + login_password: '{{ HOST.dbms_password }}' + login_port: '{{ HOST.application_port }}' + login_user: root + - name: delete database + community.mysql.mysql_db: + name: '{{ SELF.database_name }}' + state: absent + login_host: '{{ HOST.application_address }}' + login_password: '{{ HOST.dbms_password }}' + login_port: '{{ HOST.application_port }}' + login_user: root + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' mysql.database~mysql.database::ansible@mysql.dbms->gcp.cloudsql: derived_from: mysql.database metadata: @@ -9435,7 +9749,7 @@ node_types: - name: deploy database block: - name: forward port - ansible.builtin.shell: kubectl port-forward service/{{ HOST.dbms_name }} 23306:3306 + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} port-forward service/{{ HOST.dbms_name }} 23306:3306 args: executable: /usr/bin/bash async: 30 @@ -9465,7 +9779,7 @@ node_types: login_user: root always: - name: unforward port - ansible.builtin.shell: pkill -f "kubectl port-forward service/{{ HOST.dbms_name }}" + ansible.builtin.shell: pkill -f "port-forward service/{{ HOST.dbms_name }}" args: executable: /usr/bin/bash mysql.database~mysql.database::ansible@mysql.dbms->remote.machine: @@ -9525,7 +9839,40 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: delete user (with privileges) + community.mysql.mysql_user: + state: absent + name: '{{ SELF.database_user }}' + password: '{{ SELF.database_password }}' + host: '%' + priv: '*.*:ALL' + login_host: '{{ HOST.application_address }}' + login_password: '{{ HOST.dbms_password }}' + login_port: '{{ HOST.application_port }}' + login_user: root + - name: delete database + community.mysql.mysql_db: + name: '{{ SELF.database_name }}' + state: absent + login_host: '{{ HOST.application_address }}' + login_password: '{{ HOST.dbms_password }}' + login_port: '{{ HOST.application_port }}' + login_user: root + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' mysql.database~mysql.database::terraform@mysql.dbms->docker.engine->remote.machine: derived_from: mysql.database metadata: @@ -9723,7 +10070,7 @@ node_types: provisioner: local-exec: command: |- - (nohup kubectl port-forward service/{{ HOST.dbms_name }} 23306:3306 > /dev/null 2>&1 &) + (nohup kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} port-forward service/{{ HOST.dbms_name }} 23306:3306 > /dev/null 2>&1 &) sleep 5s interpreter: - /bin/bash @@ -9733,7 +10080,7 @@ node_types: - mysql_grant.user provisioner: local-exec: - command: pkill -f "kubectl port-forward service/{{ HOST.dbms_name }}" + command: pkill -f "port-forward service/{{ HOST.dbms_name }}" interpreter: - /bin/bash - '-c' @@ -9877,18 +10224,8 @@ node_types: template: spec: restartPolicy: Never - initContainers: - - name: create-database - image: mysql:{{ HOST.dbms_version }} - command: - - mysql - - '--host={{ HOST.management_address }}' - - '--port={{ HOST.management_port }}' - - '--user=root' - - '--password={{ HOST.dbms_password }}' - - '-e' - - CREATE DATABASE IF NOT EXISTS {{ SELF.database_name }} - - name: create-user + containers: + - name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}' image: mysql:{{ HOST.dbms_version }} command: - mysql @@ -9897,8 +10234,46 @@ node_types: - '--user=root' - '--password={{ HOST.dbms_password }}' - '-e' - - CREATE USER IF NOT EXISTS '{{ SELF.database_user }}'@'%' IDENTIFIED BY '{{ SELF.database_password }}' - - name: grant-privileges + - CREATE DATABASE IF NOT EXISTS {{ SELF.database_name }}; CREATE USER IF NOT EXISTS '{{ SELF.database_user }}'@'%' IDENTIFIED BY '{{ SELF.database_password }}'; GRANT ALL PRIVILEGES ON *.* TO '{{ SELF.database_user }}'@'%'; + - name: apply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} + args: + executable: /usr/bin/bash + - name: wait for deployment + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} wait --for=condition=complete --timeout=30s job/{{ SELF.database_name }}-{{ HOST.dbms_name }} + args: + executable: /usr/bin/bash + - name: cleanup + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.database_name }}-{{ HOST.dbms_name }}.database.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: '{{ job | to_yaml }}' + vars: + job: + apiVersion: batch/v1 + kind: Job + metadata: + name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}' + spec: + template: + spec: + restartPolicy: Never + containers: + - name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}' image: mysql:{{ HOST.dbms_version }} command: - mysql @@ -9907,54 +10282,39 @@ node_types: - '--user=root' - '--password={{ HOST.dbms_password }}' - '-e' - - GRANT ALL PRIVILEGES ON *.* TO '{{ SELF.database_user }}'@'%' - containers: - - name: none - image: busybox - command: - - echo - - "'done'" + - DROP USER IF EXISTS '{{ SELF.database_user }}'@'%'; DROP DATABASE IF EXISTS {{ SELF.database_name }}; - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl wait --for=condition=complete --timeout=30s job/{{ SELF.database_name }}-{{ HOST.dbms_name }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} wait --for=condition=complete --timeout=30s job/{{ SELF.database_name }}-{{ HOST.dbms_name }} args: executable: /usr/bin/bash - name: cleanup - ansible.builtin.shell: kubectl delete -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 mysql.database~mysql.database::compose@mysql.dbms->docker.engine->remote.machine: derived_from: mysql.database metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address interfaces: Standard: operations: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -9983,6 +10343,8 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' - name: give job some time ansible.builtin.pause: seconds: 10 @@ -9990,8 +10352,51 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} down args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.database_name }}-{{ HOST.dbms_name }}.database.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}-database-job' + services: + job: + container_name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}-database-job' + image: mysql:{{ HOST.dbms_version }} + network_mode: host + command: + - mysql + - '--host={{ HOST.management_address }}' + - '--port={{ HOST.management_port }}' + - '--user=root' + - '--password={{ HOST.dbms_password }}' + - '-e' + - DROP USER IF EXISTS '{{ SELF.database_user }}'@'%'; DROP DATABASE IF EXISTS {{ SELF.database_name }}; + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} up -d + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + - name: give job some time + ansible.builtin.pause: + seconds: 10 + - name: unapply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/tests/os-large/expected.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/tests/os-large/expected.yaml index 3a4f4dfbec..e96254d028 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/tests/os-large/expected.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/tests/os-large/expected.yaml @@ -377,7 +377,7 @@ topology_template: type: virtual.machine~virtual.machine#machine.image::terraform@openstack.provider properties: machine_name: unfurl-technology-boutique - ports: ['80', '9100'] + ports: ['80', '2375', '9100'] flavor: m1.large network: {get_input: os_network} ssh_key_name: {get_input: os_ssh_key_name} diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/tests/os-medium/expected.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/tests/os-medium/expected.yaml index 57d339a9b8..f92e8eed41 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/tests/os-medium/expected.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/tests/os-medium/expected.yaml @@ -377,7 +377,7 @@ topology_template: type: virtual.machine~virtual.machine#machine.image::terraform@openstack.provider properties: machine_name: unfurl-technology-boutique - ports: ['80', '9100'] + ports: ['80', '2375', '9100'] flavor: m1.medium network: {get_input: os_network} ssh_key_name: {get_input: os_ssh_key_name} diff --git a/examples/unfurl-technology---boutique---plus-maintenance-automated/variable-service-template.yaml b/examples/unfurl-technology---boutique---plus-maintenance-automated/variable-service-template.yaml index acb1227bf0..6ad33bd08c 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-automated/variable-service-template.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-automated/variable-service-template.yaml @@ -523,7 +523,7 @@ topology_template: type: virtual.machine properties: - machine_name: unfurl-technology-boutique - - ports: ['80', '9100'] + - ports: ['80', '2375', '9100'] - flavor: value: m1.medium conditions: {equal: [{variability_input: tier}, MEDIUM]} diff --git a/examples/unfurl-technology---boutique---plus-maintenance-manual/variable-service-template.yaml b/examples/unfurl-technology---boutique---plus-maintenance-manual/variable-service-template.yaml index a1b7d5261d..9d1ce8db20 100644 --- a/examples/unfurl-technology---boutique---plus-maintenance-manual/variable-service-template.yaml +++ b/examples/unfurl-technology---boutique---plus-maintenance-manual/variable-service-template.yaml @@ -625,7 +625,7 @@ topology_template: technology: terraform properties: - machine_name: unfurl-technology-boutique - - ports: ['80', '9100'] + - ports: ['80', '2375', '9100'] - flavor: value: m1.medium conditions: {equal: [{variability_input: tier}, MEDIUM]} diff --git a/examples/unfurl-technology---boutique---plus-original-automated/variable-service-template.yaml b/examples/unfurl-technology---boutique---plus-original-automated/variable-service-template.yaml index 7ce6edf64c..b0ba6f0523 100644 --- a/examples/unfurl-technology---boutique---plus-original-automated/variable-service-template.yaml +++ b/examples/unfurl-technology---boutique---plus-original-automated/variable-service-template.yaml @@ -486,7 +486,7 @@ topology_template: type: virtual.machine properties: - machine_name: unfurl-technology-boutique - - ports: ['80', '9100'] + - ports: ['80', '2375', '9100'] - flavor: value: m1.medium conditions: {equal: [{variability_input: tier}, MEDIUM]} diff --git a/examples/unfurl-technology---boutique---plus-original-manual/variable-service-template.yaml b/examples/unfurl-technology---boutique---plus-original-manual/variable-service-template.yaml index 0cc76fcda3..12e4bd042c 100644 --- a/examples/unfurl-technology---boutique---plus-original-manual/variable-service-template.yaml +++ b/examples/unfurl-technology---boutique---plus-original-manual/variable-service-template.yaml @@ -530,7 +530,7 @@ topology_template: technology: terraform properties: - machine_name: unfurl-technology-boutique - - ports: ['80', '9100'] + - ports: ['80', '2375', '9100'] - flavor: value: m1.medium conditions: {equal: [{variability_input: tier}, MEDIUM]} diff --git a/examples/unfurl-technology---shop---plus-maintenance-automated/lib/shop.component.yaml b/examples/unfurl-technology---shop---plus-maintenance-automated/lib/shop.component.yaml index 1b55d0ef12..03ae8f6d4d 100644 --- a/examples/unfurl-technology---shop---plus-maintenance-automated/lib/shop.component.yaml +++ b/examples/unfurl-technology---shop---plus-maintenance-automated/lib/shop.component.yaml @@ -126,7 +126,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' shop.component~service.application#docker.image::ansible@gcp.cloudrun: derived_from: shop.component metadata: @@ -363,7 +381,36 @@ node_types: selector: app: '{{ SELF.application_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + namespace: default + name: '{{ SELF.application_name }}' + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: app/v1 + kind: Deployment + namespace: default + name: '{{ SELF.application_name }}' shop.component~service.application#tar.archive::ansible@*->remote.machine: derived_from: shop.component metadata: @@ -3073,28 +3120,99 @@ node_types: app: '{{ SELF.application_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.application_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.application_name }} --timeout 60s + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.application.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.application_name }}' + template: + metadata: + labels: + app: '{{ SELF.application_name }}' + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + env: + - name: PORT + value: '"{{ SELF.application_port }}"' + - name: DB_DIALECT + value: '"{{ SELF.DB_DIALECT }}"' + - name: DB_NAME + value: '"{{ SELF.DB_NAME }}"' + - name: DB_USERNAME + value: '"{{ SELF.DB_USERNAME }}"' + - name: DB_PASSWORD + value: '"{{ SELF.DB_PASSWORD }}"' + - name: DB_ADDRESS + value: '"{{ SELF.DB_ADDRESS }}"' + - name: DB_PORT + value: '"{{ SELF.DB_PORT }}"' + - name: FEATURE_OPTIONAL + value: '"{{ SELF.optional_feature }}"' + - name: FEATURE_PREMIUM + value: '"{{ SELF.premium_feature }}"' + ports: + - containerPort: '{{ SELF.application_port }}' + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + namespace: default + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 shop.component~service.application#docker.image::compose@docker.engine->remote.machine: derived_from: shop.component metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -3105,14 +3223,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -3143,8 +3257,44 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.application_name }}' + services: + application: + container_name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + environment: + PORT: '"{{ SELF.application_port }}"' + DB_DIALECT: '"{{ SELF.DB_DIALECT }}"' + DB_NAME: '"{{ SELF.DB_NAME }}"' + DB_USERNAME: '"{{ SELF.DB_USERNAME }}"' + DB_PASSWORD: '"{{ SELF.DB_PASSWORD }}"' + DB_ADDRESS: '"{{ SELF.DB_ADDRESS }}"' + DB_PORT: '"{{ SELF.DB_PORT }}"' + FEATURE_OPTIONAL: '"{{ SELF.optional_feature }}"' + FEATURE_PREMIUM: '"{{ SELF.premium_feature }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/examples/unfurl-technology---shop---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml b/examples/unfurl-technology---shop---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml index e4c0368edc..0cd5780a91 100644 --- a/examples/unfurl-technology---shop---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml +++ b/examples/unfurl-technology---shop---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml @@ -673,7 +673,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: uninstall package + ansible.builtin.apt: + name: caddy + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' ingress~ingress::terraform@kubernetes.cluster: derived_from: ingress metadata: @@ -867,6 +885,6 @@ node_types: app: '{{ SELF.application_name }}' type: LoadBalancer - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash diff --git a/examples/unfurl-technology---shop---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml b/examples/unfurl-technology---shop---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml index d438d48ded..b7a204ba75 100644 --- a/examples/unfurl-technology---shop---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml +++ b/examples/unfurl-technology---shop---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml @@ -314,6 +314,7 @@ node_types: default: cloudbuild.googleapis.com docker.engine: derived_from: container.runtime + description: Installs Docker Engine listening on the unix socket as well as on tcp://0.0.0.0:2375 metadata: vintner_normative: 'true' properties: @@ -5793,6 +5794,41 @@ node_types: ansible.builtin.shell: curl -sSL https://get.docker.com | sh args: executable: /usr/bin/bash + - name: update service + ansible.builtin.copy: + dest: /lib/systemd/system/docker.service + content: | + [Unit] + Description=Docker Application Container Engine + Documentation=https://docs.docker.com + After=network-online.target docker.socket firewalld.service containerd.service time-set.target + Wants=network-online.target containerd.service + Requires=docker.socket + + [Service] + Type=notify + ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock + ExecReload=/bin/kill -s HUP $MAINPID + TimeoutStartSec=0 + RestartSec=2 + Restart=always + StartLimitBurst=3 + StartLimitInterval=60s + LimitNPROC=infinity + LimitCORE=infinity + TasksMax=infinity + Delegate=yes + KillMode=process + OOMScoreAdjust=-500 + + [Install] + WantedBy=multi-user.target + - name: restart service + ansible.builtin.systemd: + name: docker.service + state: restarted + enabled: 'yes' + daemon_reload: 'yes' - name: add docker group ansible.builtin.group: name: docker @@ -5805,7 +5841,40 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: delete docker packages + ansible.builtin.apt: + name: + - docker-ce + - docker-ce-cli + - containerd.io + - docker-buildx-plugin + - docker-compose-plugin + - docker-ce-rootless-extras + state: absent + purge: 'true' + autoremove: 'true' + - name: delete docker directories + ansible.builtin.file: + name: '{{ item }}' + state: absent + loop: + - /var/lib/docker + - /var/lib/containerd + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' docker.engine~software.application#apt.package::ansible@*->remote.machine: derived_from: docker.engine metadata: @@ -6512,11 +6581,69 @@ node_types: type: ssh user: '{{ SELF.os_ssh_user }}' provisioner: + file: + - content: | + [Unit] + Description=Docker Application Container Engine + Documentation=https://docs.docker.com + After=network-online.target docker.socket firewalld.service containerd.service time-set.target + Wants=network-online.target containerd.service + Requires=docker.socket + + [Service] + Type=notify + # the default is not to use systemd for cgroups because the delegate issues still + # exists and systemd currently does not support the cgroup feature set required + # for containers run by docker + ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock + ExecReload=/bin/kill -s HUP $MAINPID + TimeoutStartSec=0 + RestartSec=2 + Restart=always + + # Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229. + # Both the old, and new location are accepted by systemd 229 and up, so using the old location + # to make them work for either version of systemd. + StartLimitBurst=3 + + # Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230. + # Both the old, and new name are accepted by systemd 230 and up, so using the old name to make + # this option work for either version of systemd. + StartLimitInterval=60s + + # Having non-zero Limit*s causes performance problems due to accounting overhead + # in the kernel. We recommend using cgroups to do container-local accounting. + LimitNPROC=infinity + LimitCORE=infinity + + # Comment TasksMax if your systemd version does not support it. + # Only systemd 226 and above support this option. + TasksMax=infinity + + # set delegate yes so that systemd does not reset the cgroups of docker containers + Delegate=yes + + # kill only the docker process, not all processes in the cgroup + KillMode=process + OOMScoreAdjust=-500 + + [Install] + WantedBy=multi-user.target + destination: /tmp/docker.service remote-exec: - inline: - curl -sSL https://get.docker.com | sudo sh - sudo groupadd -f docker - sudo usermod -aG docker {{ SELF.os_ssh_user }} + - sleep 10s + - cat /tmp/docker.service | sudo tee /lib/systemd/system/docker.service + - sudo systemctl daemon-reload + - sudo systemctl restart docker.service + - inline: + - sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras -y + - sudo rm -rf /var/lib/docker + - sudo rm -rf /var/lib/containerd + when: destroy docker.engine~software.application#apt.archive::terraform@*->remote.machine: derived_from: docker.engine metadata: @@ -7136,7 +7263,25 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: delete container + community.docker.docker_container: + name: '{{ SELF.dbms_name }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' mysql.dbms~mysql.dbms#dbms.image::ansible@gcp.cloudsql: derived_from: mysql.dbms metadata: @@ -7331,7 +7476,36 @@ node_types: selector: app: '{{ SELF.dbms_name }}' type: ClusterIP - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + K8S_AUTH_HOST: + eval: .::k8s_host + K8S_AUTH_SSL_CA_CERT: + eval: .::k8s_ca_cert_file + K8S_AUTH_CERT_FILE: + eval: .::k8s_client_cert_file + K8S_AUTH_KEY_FILE: + eval: .::k8s_client_key_file + inputs: + playbook: + q: + - name: delete service + kubernetes.core.k8s: + state: absent + api_version: v1 + kind: Service + name: '{{ SELF.dbms_name }}' + namespace: default + - name: delete deployment + kubernetes.core.k8s: + state: absent + api_version: apps/v1 + kind: Deployment + name: '{{ SELF.dbms_name }}' + namespace: default mysql.dbms~mysql.dbms#dbms.image::ansible@remote.machine: derived_from: mysql.dbms metadata: @@ -7382,22 +7556,21 @@ node_types: q: - name: wait for ssh wait_for_connection: - - name: Installing mysql + - name: installing mysql ansible.builtin.apt: - name: '{{ item }}' + name: + - mysql-server + - mysql-client + - python3-mysqldb + - libmysqlclient-dev state: present update_cache: 'yes' - loop: - - mysql-server - - mysql-client - - python3-mysqldb - - libmysqlclient-dev - - name: Start and enable mysql service + - name: start and enable mysql service ansible.builtin.systemd: name: mysql state: started enabled: 'yes' - - name: Enable passwordless login + - name: enable passwordless login ansible.builtin.copy: dest: '{{ item }}' content: | @@ -7407,23 +7580,23 @@ node_types: loop: - /root/.my.cnf - /home/{{ SELF.os_ssh_user }}/.my.cnf - - name: Configure port (e.g., since 3306 is blocked by the provider) + - name: configure port (e.g., since 3306 is blocked by the provider) ansible.builtin.lineinfile: path: /etc/mysql/mysql.conf.d/mysqld.cnf regexp: ^# port line: port = {{ SELF.application_port }} backup: 'yes' - - name: Enable remote login + - name: enable remote login ansible.builtin.lineinfile: path: /etc/mysql/mysql.conf.d/mysqld.cnf regexp: ^bind-address line: bind-address = 0.0.0.0 backup: 'yes' - - name: Restart mysql + - name: restart mysql ansible.builtin.systemd: name: mysql state: restarted - - name: Create all root + - name: create all root community.mysql.mysql_user: name: root password: '{{ SELF.dbms_password }}' @@ -7434,7 +7607,7 @@ node_types: login_password: '{{ SELF.dbms_password }}' login_port: '{{ SELF.application_port }}' login_user: root - - name: Delete localhost root + - name: delete localhost root community.mysql.mysql_user: name: root host: localhost @@ -7447,7 +7620,36 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: uninstalling mysql + ansible.builtin.apt: + name: + - mysql-server + - mysql-client + - python3-mysqldb + - libmysqlclient-dev + state: absent + - name: remove passwordless login + ansible.builtin.file: + name: '{{ item }}' + state: absent + loop: + - /root/.my.cnf + - /home/{{ SELF.os_ssh_user }}/.my.cnf + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' mysql.dbms~software.application#apt.package::ansible@*->remote.machine: derived_from: mysql.dbms metadata: @@ -9152,31 +9354,86 @@ node_types: app: '{{ SELF.dbms_name }}' type: ClusterIP - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl rollout status deployment/{{ SELF.dbms_name }} --timeout 60s + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} rollout status deployment/{{ SELF.dbms_name }} --timeout 60s args: executable: /usr/bin/bash - - name: give DBMS some time + - name: let it cook ansible.builtin.pause: seconds: 10 - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.dbms_name }}.dbms.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: | + {{ deployment | to_yaml }} + --- + {{ service | to_yaml }} + vars: + deployment: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: '{{ SELF.dbms_name }}' + namespace: default + spec: + selector: + matchLabels: + app: '{{ SELF.dbms_name }}' + template: + metadata: + labels: + app: '{{ SELF.dbms_name }}' + spec: + containers: + - image: mysql:{{ ".artifacts::dbms_image::file" | eval }} + name: '{{ SELF.dbms_name }}' + env: + - name: MYSQL_ROOT_PASSWORD + value: '{{ SELF.dbms_password }}' + ports: + - containerPort: 3306 + name: mysql + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.dbms_name }}' + spec: + ports: + - name: mysql + port: 3306 + targetPort: 3306 + selector: + app: '{{ SELF.dbms_name }}' + type: ClusterIP + - name: unapply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} + args: + executable: /usr/bin/bash mysql.dbms~mysql.dbms#dbms.image::compose@docker.engine->remote.machine: derived_from: mysql.dbms metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address attributes: application_address: type: string @@ -9204,14 +9461,10 @@ node_types: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -9234,14 +9487,42 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - - name: give DBMS some time + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + - name: let it cook ansible.builtin.pause: seconds: 10 - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.dbms_name }}.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.dbms_name }}' + services: + application: + container_name: '{{ SELF.dbms_name }}' + image: mysql:{{ ".artifacts::dbms_image::file" | eval }} + network_mode: host + environment: + MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password }}' + - name: unapply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' mysql.database~mysql.database::ansible@mysql.dbms->docker.engine->remote.machine: derived_from: mysql.database metadata: @@ -9330,7 +9611,40 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: delete user (with privileges) + community.mysql.mysql_user: + state: absent + name: '{{ SELF.database_user }}' + password: '{{ SELF.database_password }}' + host: '%' + priv: '*.*:ALL' + login_host: '{{ HOST.application_address }}' + login_password: '{{ HOST.dbms_password }}' + login_port: '{{ HOST.application_port }}' + login_user: root + - name: delete database + community.mysql.mysql_db: + name: '{{ SELF.database_name }}' + state: absent + login_host: '{{ HOST.application_address }}' + login_password: '{{ HOST.dbms_password }}' + login_port: '{{ HOST.application_port }}' + login_user: root + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' mysql.database~mysql.database::ansible@mysql.dbms->gcp.cloudsql: derived_from: mysql.database metadata: @@ -9435,7 +9749,7 @@ node_types: - name: deploy database block: - name: forward port - ansible.builtin.shell: kubectl port-forward service/{{ HOST.dbms_name }} 23306:3306 + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} port-forward service/{{ HOST.dbms_name }} 23306:3306 args: executable: /usr/bin/bash async: 30 @@ -9465,7 +9779,7 @@ node_types: login_user: root always: - name: unforward port - ansible.builtin.shell: pkill -f "kubectl port-forward service/{{ HOST.dbms_name }}" + ansible.builtin.shell: pkill -f "port-forward service/{{ HOST.dbms_name }}" args: executable: /usr/bin/bash mysql.database~mysql.database::ansible@mysql.dbms->remote.machine: @@ -9525,7 +9839,40 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: delete user (with privileges) + community.mysql.mysql_user: + state: absent + name: '{{ SELF.database_user }}' + password: '{{ SELF.database_password }}' + host: '%' + priv: '*.*:ALL' + login_host: '{{ HOST.application_address }}' + login_password: '{{ HOST.dbms_password }}' + login_port: '{{ HOST.application_port }}' + login_user: root + - name: delete database + community.mysql.mysql_db: + name: '{{ SELF.database_name }}' + state: absent + login_host: '{{ HOST.application_address }}' + login_password: '{{ HOST.dbms_password }}' + login_port: '{{ HOST.application_port }}' + login_user: root + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' mysql.database~mysql.database::terraform@mysql.dbms->docker.engine->remote.machine: derived_from: mysql.database metadata: @@ -9723,7 +10070,7 @@ node_types: provisioner: local-exec: command: |- - (nohup kubectl port-forward service/{{ HOST.dbms_name }} 23306:3306 > /dev/null 2>&1 &) + (nohup kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} port-forward service/{{ HOST.dbms_name }} 23306:3306 > /dev/null 2>&1 &) sleep 5s interpreter: - /bin/bash @@ -9733,7 +10080,7 @@ node_types: - mysql_grant.user provisioner: local-exec: - command: pkill -f "kubectl port-forward service/{{ HOST.dbms_name }}" + command: pkill -f "port-forward service/{{ HOST.dbms_name }}" interpreter: - /bin/bash - '-c' @@ -9877,18 +10224,8 @@ node_types: template: spec: restartPolicy: Never - initContainers: - - name: create-database - image: mysql:{{ HOST.dbms_version }} - command: - - mysql - - '--host={{ HOST.management_address }}' - - '--port={{ HOST.management_port }}' - - '--user=root' - - '--password={{ HOST.dbms_password }}' - - '-e' - - CREATE DATABASE IF NOT EXISTS {{ SELF.database_name }} - - name: create-user + containers: + - name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}' image: mysql:{{ HOST.dbms_version }} command: - mysql @@ -9897,8 +10234,46 @@ node_types: - '--user=root' - '--password={{ HOST.dbms_password }}' - '-e' - - CREATE USER IF NOT EXISTS '{{ SELF.database_user }}'@'%' IDENTIFIED BY '{{ SELF.database_password }}' - - name: grant-privileges + - CREATE DATABASE IF NOT EXISTS {{ SELF.database_name }}; CREATE USER IF NOT EXISTS '{{ SELF.database_user }}'@'%' IDENTIFIED BY '{{ SELF.database_password }}'; GRANT ALL PRIVILEGES ON *.* TO '{{ SELF.database_user }}'@'%'; + - name: apply manifest + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} + args: + executable: /usr/bin/bash + - name: wait for deployment + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} wait --for=condition=complete --timeout=30s job/{{ SELF.database_name }}-{{ HOST.dbms_name }} + args: + executable: /usr/bin/bash + - name: cleanup + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} + args: + executable: /usr/bin/bash + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.database_name }}-{{ HOST.dbms_name }}.database.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: '{{ job | to_yaml }}' + vars: + job: + apiVersion: batch/v1 + kind: Job + metadata: + name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}' + spec: + template: + spec: + restartPolicy: Never + containers: + - name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}' image: mysql:{{ HOST.dbms_version }} command: - mysql @@ -9907,54 +10282,39 @@ node_types: - '--user=root' - '--password={{ HOST.dbms_password }}' - '-e' - - GRANT ALL PRIVILEGES ON *.* TO '{{ SELF.database_user }}'@'%' - containers: - - name: none - image: busybox - command: - - echo - - "'done'" + - DROP USER IF EXISTS '{{ SELF.database_user }}'@'%'; DROP DATABASE IF EXISTS {{ SELF.database_name }}; - name: apply manifest - ansible.builtin.shell: kubectl apply -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} apply -f {{ manifest.path }} args: executable: /usr/bin/bash - name: wait for deployment - ansible.builtin.shell: kubectl wait --for=condition=complete --timeout=30s job/{{ SELF.database_name }}-{{ HOST.dbms_name }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} wait --for=condition=complete --timeout=30s job/{{ SELF.database_name }}-{{ HOST.dbms_name }} args: executable: /usr/bin/bash - name: cleanup - ansible.builtin.shell: kubectl delete -f {{ manifest.path }} + ansible.builtin.shell: kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }} delete -f {{ manifest.path }} args: executable: /usr/bin/bash - delete: exit 0 mysql.database~mysql.database::compose@mysql.dbms->docker.engine->remote.machine: derived_from: mysql.database metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + os_ssh_host: type: string default: - get_input: os_ssh_key_file + eval: .::.requirements::[.name=host]::.target::management_address interfaces: Standard: operations: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + operation_host: ORCHESTRATOR inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - name: touch compose register: compose ansible.builtin.tempfile: @@ -9983,6 +10343,8 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' - name: give job some time ansible.builtin.pause: seconds: 10 @@ -9990,8 +10352,51 @@ node_types: ansible.builtin.shell: docker compose -f {{ compose.path }} down args: executable: /usr/bin/bash - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: exit 0 + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.database_name }}-{{ HOST.dbms_name }}.database.compose.yaml' + - name: create compose + ansible.builtin.copy: + dest: '{{ compose.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}-database-job' + services: + job: + container_name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}-database-job' + image: mysql:{{ HOST.dbms_version }} + network_mode: host + command: + - mysql + - '--host={{ HOST.management_address }}' + - '--port={{ HOST.management_port }}' + - '--user=root' + - '--password={{ HOST.dbms_password }}' + - '-e' + - DROP USER IF EXISTS '{{ SELF.database_user }}'@'%'; DROP DATABASE IF EXISTS {{ SELF.database_name }}; + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} up -d + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + - name: give job some time + ansible.builtin.pause: + seconds: 10 + - name: unapply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' diff --git a/package.json b/package.json index b6bc74204e..74261fdf39 100644 --- a/package.json +++ b/package.json @@ -46,8 +46,8 @@ "fs-extra": "^11.2.0", "glob": "^10.4.1", "http-errors": "^2.0.0", - "ini": "^4.1.3", "is-wsl": "^2.2.0", + "js-ini": "^1.6.0", "js-yaml": "^4.1.0", "json-diff": "^1.0.6", "lnk": "^1.1.0", diff --git a/src/normative/types/extended/nodes.ts b/src/normative/types/extended/nodes.ts index e34208a827..f41f2e9338 100644 --- a/src/normative/types/extended/nodes.ts +++ b/src/normative/types/extended/nodes.ts @@ -339,6 +339,7 @@ const nodes: NodeTypeMap = { }, 'docker.engine': { derived_from: 'container.runtime', + description: 'Installs Docker Engine listening on the unix socket as well as on tcp://0.0.0.0:2375', metadata: { ...MetadataNormative(), }, diff --git a/src/technologies/plugins/rules/generators/docker-engine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/docker-engine/remote-machine/ansible/index.ts index dc02c1852c..dc2f9813f5 100644 --- a/src/technologies/plugins/rules/generators/docker-engine/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/docker-engine/remote-machine/ansible/index.ts @@ -1,3 +1,4 @@ +import * as files from '#files' import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleHostOperation, @@ -17,6 +18,36 @@ const generator: ImplementationGenerator = { details: '"ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks', generate: (name, type) => { + const service = files.toINI({ + Unit: { + Description: 'Docker Application Container Engine', + Documentation: 'https://docs.docker.com', + After: 'network-online.target docker.socket firewalld.service containerd.service time-set.target', + Wants: 'network-online.target containerd.service', + Requires: 'docker.socket', + }, + Service: { + Type: 'notify', + ExecStart: + '/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock', + ExecReload: '/bin/kill -s HUP $MAINPID', + TimeoutStartSec: '0', + RestartSec: '2', + Restart: 'always', + StartLimitBurst: '3', + StartLimitInterval: '60s', + LimitNPROC: 'infinity', + LimitCORE: 'infinity', + TasksMax: 'infinity', + Delegate: 'yes', + KillMode: 'process', + OOMScoreAdjust: '-500', + }, + Install: { + WantedBy: 'multi-user.target', + }, + }) + return { derived_from: name, metadata: { @@ -44,6 +75,22 @@ const generator: ImplementationGenerator = { executable: '/usr/bin/bash', }, }, + { + name: 'update service', + 'ansible.builtin.copy': { + dest: '/lib/systemd/system/docker.service', + content: service, + }, + }, + { + name: 'restart service', + 'ansible.builtin.systemd': { + name: 'docker.service', + state: 'restarted', + enabled: 'yes', + daemon_reload: 'yes', + }, + }, { name: 'add docker group', 'ansible.builtin.group': { @@ -63,7 +110,46 @@ const generator: ImplementationGenerator = { playbookArgs: [...AnsibleHostOperationPlaybookArgs()], }, }, - delete: 'exit 0', + delete: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + // https://docs.docker.com/engine/install/ubuntu/#uninstall-docker-engine + { + name: 'delete docker packages', + 'ansible.builtin.apt': { + name: [ + 'docker-ce', + 'docker-ce-cli', + 'containerd.io', + 'docker-buildx-plugin', + 'docker-compose-plugin', + 'docker-ce-rootless-extras', + ], + state: 'absent', + purge: 'true', + autoremove: 'true', + }, + }, + { + name: 'delete docker directories', + 'ansible.builtin.file': { + name: '{{ item }}', + state: 'absent', + }, + loop: ['/var/lib/docker', '/var/lib/containerd'], + }, + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, }, }, }, diff --git a/src/technologies/plugins/rules/generators/docker-engine/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/docker-engine/remote-machine/terraform/index.ts index f9b1661f7a..86fb3f0150 100644 --- a/src/technologies/plugins/rules/generators/docker-engine/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/docker-engine/remote-machine/terraform/index.ts @@ -6,6 +6,56 @@ import { OpenstackMachineHost, TerraformStandardOperations, } from '#technologies/plugins/rules/utils' +import * as utils from '#utils' + +const service = utils.trim(` +[Unit] +Description=Docker Application Container Engine +Documentation=https://docs.docker.com +After=network-online.target docker.socket firewalld.service containerd.service time-set.target +Wants=network-online.target containerd.service +Requires=docker.socket + +[Service] +Type=notify +# the default is not to use systemd for cgroups because the delegate issues still +# exists and systemd currently does not support the cgroup feature set required +# for containers run by docker +ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock +ExecReload=/bin/kill -s HUP $MAINPID +TimeoutStartSec=0 +RestartSec=2 +Restart=always + +# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229. +# Both the old, and new location are accepted by systemd 229 and up, so using the old location +# to make them work for either version of systemd. +StartLimitBurst=3 + +# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230. +# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make +# this option work for either version of systemd. +StartLimitInterval=60s + +# Having non-zero Limit*s causes performance problems due to accounting overhead +# in the kernel. We recommend using cgroups to do container-local accounting. +LimitNPROC=infinity +LimitCORE=infinity + +# Comment TasksMax if your systemd version does not support it. +# Only systemd 226 and above support this option. +TasksMax=infinity + +# set delegate yes so that systemd does not reset the cgroups of docker containers +Delegate=yes + +# kill only the docker process, not all processes in the cgroup +KillMode=process +OOMScoreAdjust=-500 + +[Install] +WantedBy=multi-user.target +`) const generator: ImplementationGenerator = { component: 'docker.engine', @@ -51,13 +101,32 @@ const generator: ImplementationGenerator = { }, ], provisioner: { + file: [ + { + content: service, + destination: '/tmp/docker.service', + }, + ], 'remote-exec': [ { inline: [ 'curl -sSL https://get.docker.com | sudo sh', 'sudo groupadd -f docker', 'sudo usermod -aG docker {{ SELF.os_ssh_user }}', + 'sleep 10s', + 'cat /tmp/docker.service | sudo tee /lib/systemd/system/docker.service', + 'sudo systemctl daemon-reload', + 'sudo systemctl restart docker.service', + ], + }, + // https://docs.docker.com/engine/install/ubuntu/#uninstall-docker-engine + { + inline: [ + 'sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras -y', + 'sudo rm -rf /var/lib/docker', + 'sudo rm -rf /var/lib/containerd', ], + when: 'destroy', }, ], }, diff --git a/src/technologies/plugins/rules/generators/gcp-service/ansible/index.ts b/src/technologies/plugins/rules/generators/gcp-service/ansible/index.ts index 3b4db82833..27b3f29386 100644 --- a/src/technologies/plugins/rules/generators/gcp-service/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/gcp-service/ansible/index.ts @@ -51,6 +51,7 @@ const generator: ImplementationGenerator = { }, }, }, + // We do not disable gcp services delete: 'exit 0', }, }, diff --git a/src/technologies/plugins/rules/generators/ingress/kubernetes-cluster/ansible/index.ts b/src/technologies/plugins/rules/generators/ingress/kubernetes-cluster/ansible/index.ts index 8f60085a33..8f7b352ca5 100644 --- a/src/technologies/plugins/rules/generators/ingress/kubernetes-cluster/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/ingress/kubernetes-cluster/ansible/index.ts @@ -1,5 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleKubernetesCredentialsEnvironment, AnsibleOrchestratorOperation, KubernetesCredentials, MetadataGenerated, @@ -36,18 +37,7 @@ const generator: ImplementationGenerator = { implementation: { ...AnsibleOrchestratorOperation(), environment: { - K8S_AUTH_HOST: { - eval: '.::k8s_host', - }, - K8S_AUTH_SSL_CA_CERT: { - eval: '.::k8s_ca_cert_file', - }, - K8S_AUTH_CERT_FILE: { - eval: '.::k8s_client_cert_file', - }, - K8S_AUTH_KEY_FILE: { - eval: '.::k8s_client_key_file', - }, + ...AnsibleKubernetesCredentialsEnvironment(), }, }, inputs: { diff --git a/src/technologies/plugins/rules/generators/ingress/kubernetes-cluster/kubernetes/index.ts b/src/technologies/plugins/rules/generators/ingress/kubernetes-cluster/kubernetes/index.ts index 55ae6bad6a..f63bdcef0f 100644 --- a/src/technologies/plugins/rules/generators/ingress/kubernetes-cluster/kubernetes/index.ts +++ b/src/technologies/plugins/rules/generators/ingress/kubernetes-cluster/kubernetes/index.ts @@ -1,13 +1,12 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleOrchestratorOperation, + BASH_KUBECTL, KubernetesCredentials, MetadataGenerated, MetadataUnfurl, } from '#technologies/plugins/rules/utils' -// TODO: does not use k8s auth - const generator: ImplementationGenerator = { component: 'ingress', technology: 'kubernetes', @@ -79,7 +78,7 @@ const generator: ImplementationGenerator = { }, { name: 'apply manifest', - 'ansible.builtin.shell': 'kubectl apply -f {{ manifest.path }}', + 'ansible.builtin.shell': `${BASH_KUBECTL} apply -f {{ manifest.path }}`, args: { executable: '/usr/bin/bash', }, diff --git a/src/technologies/plugins/rules/generators/ingress/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/ingress/remote-machine/ansible/index.ts index e2d839711e..9b6866dc3d 100644 --- a/src/technologies/plugins/rules/generators/ingress/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/ingress/remote-machine/ansible/index.ts @@ -91,7 +91,28 @@ const generator: ImplementationGenerator = { playbookArgs: [...AnsibleHostOperationPlaybookArgs()], }, }, - delete: 'exit 0', + delete: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + { + name: 'uninstall package', + 'ansible.builtin.apt': { + name: 'caddy', + state: 'absent', + }, + }, + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, }, }, }, diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/index.ts index a6f4d21dc1..37846c4803 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/index.ts @@ -1,3 +1,3 @@ -import remoteMachine from './virtual-machine' +import remoteMachine from './remote-machine' export default [remoteMachine] diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/virtual-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/ansible/index.ts similarity index 75% rename from src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/virtual-machine/ansible/index.ts rename to src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/ansible/index.ts index 5d8e6dc51c..23ae0c7f83 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/virtual-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/ansible/index.ts @@ -24,6 +24,20 @@ const generator: ImplementationGenerator = { reason: 'Primary use case due to the specialization of Ansible.', generate: (name, type) => { + const user = { + name: '{{ SELF.database_user }}', + password: '{{ SELF.database_password }}', + host: '%', + priv: '*.*:ALL', + } + + const login = { + login_host: '{{ HOST.application_address }}', + login_password: '{{ HOST.dbms_password }}', + login_port: '{{ HOST.application_port }}', + login_user: 'root', + } + return { derived_from: name, metadata: { @@ -92,23 +106,14 @@ const generator: ImplementationGenerator = { name: 'create database', 'community.mysql.mysql_db': { name: '{{ SELF.database_name }}', - login_host: '{{ HOST.application_address }}', - login_password: '{{ HOST.dbms_password }}', - login_port: '{{ HOST.application_port }}', - login_user: 'root', + ...login, }, }, { name: 'create user (with privileges)', 'community.mysql.mysql_user': { - name: '{{ SELF.database_user }}', - password: '{{ SELF.database_password }}', - host: '%', - priv: '*.*:ALL', - login_host: '{{ HOST.application_address }}', - login_password: '{{ HOST.dbms_password }}', - login_port: '{{ HOST.application_port }}', - login_user: 'root', + ...user, + ...login, }, }, { @@ -134,7 +139,37 @@ const generator: ImplementationGenerator = { playbookArgs: [...AnsibleHostOperationPlaybookArgs()], }, }, - delete: 'exit 0', + delete: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + { + name: 'delete user (with privileges)', + 'community.mysql.mysql_user': { + state: 'absent', + ...user, + ...login, + }, + }, + { + name: 'delete database', + 'community.mysql.mysql_db': { + name: '{{ SELF.database_name }}', + state: 'absent', + ...login, + }, + }, + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, }, }, }, diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/compose/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/compose/index.ts new file mode 100644 index 0000000000..cbdda353bd --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/compose/index.ts @@ -0,0 +1,139 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleDockerHostEnvironment, + AnsibleOrchestratorOperation, + MetadataGenerated, + MetadataUnfurl, + OpenstackMachineHost, +} from '#technologies/plugins/rules/utils' + +// TODO: we assume that dbms is exposed + +const generator: ImplementationGenerator = { + component: 'mysql.database', + technology: 'compose', + hosting: ['mysql.dbms', 'docker.engine', 'remote.machine'], + weight: 0, + reason: 'One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules.', + + generate: (name, type) => { + const AnsibleTouchJobTask = { + name: 'touch compose', + register: 'compose', + 'ansible.builtin.tempfile': { + suffix: '{{ SELF.database_name }}-{{ HOST.dbms_name }}.database.compose.yaml', + }, + } + + const AnsibleCreateJobTask = (query: string) => { + return { + name: 'create compose', + 'ansible.builtin.copy': { + dest: '{{ compose.path }}', + content: '{{ manifest | to_yaml }}', + }, + vars: { + manifest: { + name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}-database-job', + services: { + job: { + container_name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}-database-job', + image: 'mysql:{{ HOST.dbms_version }}', + network_mode: 'host', + command: [ + 'mysql', + '--host={{ HOST.management_address }}', + '--port={{ HOST.management_port }}', + '--user=root', + '--password={{ HOST.dbms_password }}', + '-e', + query, + ], + }, + }, + }, + }, + } + } + + const AnsibleApplyJobTasks = [ + { + name: 'apply compose', + 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', + args: { + executable: '/usr/bin/bash', + }, + environment: { + ...AnsibleDockerHostEnvironment(), + }, + }, + { + name: 'give job some time', + 'ansible.builtin.pause': { + seconds: 10, + }, + }, + { + name: 'unapply compose', + 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', + args: { + executable: '/usr/bin/bash', + }, + environment: { + ...AnsibleDockerHostEnvironment(), + }, + }, + ] + + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...OpenstackMachineHost(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + AnsibleTouchJobTask, + AnsibleCreateJobTask( + "CREATE DATABASE IF NOT EXISTS {{ SELF.database_name }}; CREATE USER IF NOT EXISTS '{{ SELF.database_user }}'@'%' IDENTIFIED BY '{{ SELF.database_password }}'; GRANT ALL PRIVILEGES ON *.* TO '{{ SELF.database_user }}'@'%';" + ), + ...AnsibleApplyJobTasks, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + AnsibleTouchJobTask, + AnsibleCreateJobTask( + "DROP USER IF EXISTS '{{ SELF.database_user }}'@'%'; DROP DATABASE IF EXISTS {{ SELF.database_name }};" + ), + ...AnsibleApplyJobTasks, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/virtual-machine/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/virtual-machine/index.ts rename to src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/virtual-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/terraform/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/virtual-machine/terraform/index.ts rename to src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/terraform/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/virtual-machine/compose/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/virtual-machine/compose/index.ts deleted file mode 100644 index 7255c84f76..0000000000 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/virtual-machine/compose/index.ts +++ /dev/null @@ -1,112 +0,0 @@ -import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - AnsibleHostOperation, - AnsibleHostOperationPlaybookArgs, - AnsibleWaitForSSHTask, - MetadataGenerated, - MetadataUnfurl, - OpenstackMachineCredentials, -} from '#technologies/plugins/rules/utils' - -// TODO: we assume that dbms is exposed - -const generator: ImplementationGenerator = { - component: 'mysql.database', - technology: 'compose', - hosting: ['mysql.dbms', 'docker.engine', 'remote.machine'], - weight: 0, - reason: 'One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules.', - - generate: (name, type) => { - return { - derived_from: name, - metadata: { - ...MetadataGenerated(), - ...MetadataUnfurl(), - }, - properties: { - ...OpenstackMachineCredentials(), - }, - interfaces: { - Standard: { - operations: { - create: { - implementation: { - ...AnsibleHostOperation(), - }, - inputs: { - playbook: { - q: [ - { - ...AnsibleWaitForSSHTask(), - }, - { - name: 'touch compose', - register: 'compose', - 'ansible.builtin.tempfile': { - suffix: '{{ SELF.database_name }}-{{ HOST.dbms_name }}.database.compose.yaml', - }, - }, - { - name: 'create compose', - 'ansible.builtin.copy': { - dest: '{{ compose.path }}', - content: '{{ manifest | to_yaml }}', - }, - vars: { - manifest: { - name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}-database-job', - services: { - job: { - container_name: - '{{ SELF.database_name }}-{{ HOST.dbms_name }}-database-job', - image: 'mysql:{{ HOST.dbms_version }}', - network_mode: 'host', - command: [ - 'mysql', - '--host={{ HOST.management_address }}', - '--port={{ HOST.management_port }}', - '--user=root', - '--password={{ HOST.dbms_password }}', - '-e', - "CREATE DATABASE IF NOT EXISTS {{ SELF.database_name }}; CREATE USER IF NOT EXISTS '{{ SELF.database_user }}'@'%' IDENTIFIED BY '{{ SELF.database_password }}'; GRANT ALL PRIVILEGES ON *.* TO '{{ SELF.database_user }}'@'%';", - ], - }, - }, - }, - }, - }, - { - name: 'apply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', - args: { - executable: '/usr/bin/bash', - }, - }, - { - name: 'give job some time', - 'ansible.builtin.pause': { - seconds: 10, - }, - }, - { - name: 'unapply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', - args: { - executable: '/usr/bin/bash', - }, - }, - ], - }, - playbookArgs: [...AnsibleHostOperationPlaybookArgs()], - }, - }, - delete: 'exit 0', - }, - }, - }, - } - }, -} - -export default generator diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/kubernetes-cluster/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/kubernetes-cluster/ansible/index.ts index c6f976de52..090e900d91 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/kubernetes-cluster/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/kubernetes-cluster/ansible/index.ts @@ -1,13 +1,12 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleOrchestratorOperation, + BASH_KUBECTL, KubernetesCredentials, MetadataGenerated, MetadataUnfurl, } from '#technologies/plugins/rules/utils' -// TODO: use k8s auth - const generator: ImplementationGenerator = { component: 'mysql.database', technology: 'ansible', @@ -40,8 +39,7 @@ const generator: ImplementationGenerator = { block: [ { name: 'forward port', - 'ansible.builtin.shell': - 'kubectl port-forward service/{{ HOST.dbms_name }} 23306:3306', + 'ansible.builtin.shell': `${BASH_KUBECTL} port-forward service/{{ HOST.dbms_name }} 23306:3306`, args: { executable: '/usr/bin/bash', }, @@ -85,7 +83,7 @@ const generator: ImplementationGenerator = { { name: 'unforward port', 'ansible.builtin.shell': - 'pkill -f "kubectl port-forward service/{{ HOST.dbms_name }}"', + 'pkill -f "port-forward service/{{ HOST.dbms_name }}"', args: { executable: '/usr/bin/bash', }, diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/kubernetes-cluster/kubernetes/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/kubernetes-cluster/kubernetes/index.ts index 0baa0120a1..9a88d82b01 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/kubernetes-cluster/kubernetes/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/kubernetes-cluster/kubernetes/index.ts @@ -1,13 +1,12 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleOrchestratorOperation, + BASH_KUBECTL, KubernetesCredentials, MetadataGenerated, MetadataUnfurl, } from '#technologies/plugins/rules/utils' -// TODO: does not use k8s auth - const generator: ImplementationGenerator = { component: 'mysql.database', technology: 'kubernetes', @@ -16,6 +15,80 @@ const generator: ImplementationGenerator = { reason: 'Kubernetes Job with imperative parts, while declarative other technologies provide declarative modules.', generate: (name, type) => { + const AnsibleTouchJobTask = { + name: 'touch manifest', + register: 'manifest', + 'ansible.builtin.tempfile': { + suffix: '{{ SELF.database_name }}-{{ HOST.dbms_name }}.database.manifest.yaml', + }, + } + + const AnsibleCreateJobTask = (query: string) => { + return { + name: 'create manifest', + 'ansible.builtin.copy': { + dest: '{{ manifest.path }}', + content: '{{ job | to_yaml }}', + }, + vars: { + job: { + apiVersion: 'batch/v1', + kind: 'Job', + metadata: { + name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}', + }, + spec: { + template: { + spec: { + restartPolicy: 'Never', + containers: [ + { + name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}', + image: 'mysql:{{ HOST.dbms_version }}', + command: [ + 'mysql', + '--host={{ HOST.management_address }}', + '--port={{ HOST.management_port }}', + '--user=root', + '--password={{ HOST.dbms_password }}', + '-e', + query, + ], + }, + ], + }, + }, + }, + }, + }, + } + } + + const AnsibleApplyJobTasks = [ + { + name: 'apply manifest', + 'ansible.builtin.shell': `${BASH_KUBECTL} apply -f {{ manifest.path }}`, + args: { + executable: '/usr/bin/bash', + }, + }, + { + name: 'wait for deployment', + 'ansible.builtin.shell': `${BASH_KUBECTL} wait --for=condition=complete --timeout=30s job/{{ SELF.database_name }}-{{ HOST.dbms_name }}`, + args: { + executable: '/usr/bin/bash', + }, + }, + + { + name: 'cleanup', + 'ansible.builtin.shell': `${BASH_KUBECTL} delete -f {{ manifest.path }}`, + args: { + executable: '/usr/bin/bash', + }, + }, + ] + return { derived_from: name, metadata: { @@ -35,113 +108,31 @@ const generator: ImplementationGenerator = { inputs: { playbook: { q: [ - { - name: 'touch manifest', - register: 'manifest', - 'ansible.builtin.tempfile': { - suffix: '{{ SELF.database_name }}-{{ HOST.dbms_name }}.database.manifest.yaml', - }, - }, - { - name: 'create manifest', - 'ansible.builtin.copy': { - dest: '{{ manifest.path }}', - content: '{{ job | to_yaml }}', - }, - vars: { - job: { - apiVersion: 'batch/v1', - kind: 'Job', - metadata: { - name: '{{ SELF.database_name }}-{{ HOST.dbms_name }}', - }, - spec: { - template: { - spec: { - restartPolicy: 'Never', - initContainers: [ - { - name: 'create-database', - image: 'mysql:{{ HOST.dbms_version }}', - command: [ - 'mysql', - '--host={{ HOST.management_address }}', - '--port={{ HOST.management_port }}', - '--user=root', - '--password={{ HOST.dbms_password }}', - '-e', - 'CREATE DATABASE IF NOT EXISTS {{ SELF.database_name }}', - ], - }, - { - name: 'create-user', - image: 'mysql:{{ HOST.dbms_version }}', - command: [ - 'mysql', - '--host={{ HOST.management_address }}', - '--port={{ HOST.management_port }}', - '--user=root', - '--password={{ HOST.dbms_password }}', - '-e', - "CREATE USER IF NOT EXISTS '{{ SELF.database_user }}'@'%' IDENTIFIED BY '{{ SELF.database_password }}'", - ], - }, - { - name: 'grant-privileges', - image: 'mysql:{{ HOST.dbms_version }}', - command: [ - 'mysql', - '--host={{ HOST.management_address }}', - '--port={{ HOST.management_port }}', - '--user=root', - '--password={{ HOST.dbms_password }}', - '-e', - "GRANT ALL PRIVILEGES ON *.* TO '{{ SELF.database_user }}'@'%'", - ], - }, - ], - containers: [ - { - name: 'none', - image: 'busybox', - command: ['echo', "'done'"], - }, - ], - }, - }, - }, - }, - }, - }, - { - name: 'apply manifest', - 'ansible.builtin.shell': 'kubectl apply -f {{ manifest.path }}', - args: { - executable: '/usr/bin/bash', - }, - }, - - { - name: 'wait for deployment', - 'ansible.builtin.shell': - 'kubectl wait --for=condition=complete --timeout=30s job/{{ SELF.database_name }}-{{ HOST.dbms_name }}', - args: { - executable: '/usr/bin/bash', - }, - }, - - { - name: 'cleanup', - 'ansible.builtin.shell': 'kubectl delete -f {{ manifest.path }}', - args: { - executable: '/usr/bin/bash', - }, - }, + AnsibleTouchJobTask, + AnsibleCreateJobTask( + "CREATE DATABASE IF NOT EXISTS {{ SELF.database_name }}; CREATE USER IF NOT EXISTS '{{ SELF.database_user }}'@'%' IDENTIFIED BY '{{ SELF.database_password }}'; GRANT ALL PRIVILEGES ON *.* TO '{{ SELF.database_user }}'@'%';" + ), + ...AnsibleApplyJobTasks, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + AnsibleTouchJobTask, + AnsibleCreateJobTask( + "DROP USER IF EXISTS '{{ SELF.database_user }}'@'%'; DROP DATABASE IF EXISTS {{ SELF.database_name }};" + ), + ...AnsibleApplyJobTasks, ], }, }, }, - delete: 'exit 0', }, }, }, diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/kubernetes-cluster/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/kubernetes-cluster/terraform/index.ts index a24e488f48..8d4e28b485 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/kubernetes-cluster/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/kubernetes-cluster/terraform/index.ts @@ -1,13 +1,12 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + BASH_KUBECTL, KubernetesCredentials, MetadataGenerated, MetadataUnfurl, TerraformStandardOperations, } from '#technologies/plugins/rules/utils' -// TODO: use k8s auth - /** * Official Kubernetes provider does not provide "kubectl exec", https://registry.terraform.io/providers/hashicorp/kubernetes */ @@ -74,7 +73,7 @@ const generator: ImplementationGenerator = { provisioner: { 'local-exec': { command: [ - '(nohup kubectl port-forward service/{{ HOST.dbms_name }} 23306:3306 > /dev/null 2>&1 &)', + `(nohup ${BASH_KUBECTL} port-forward service/{{ HOST.dbms_name }} 23306:3306 > /dev/null 2>&1 &)`, 'sleep 5s', ].join('\n'), interpreter: ['/bin/bash', '-c'], @@ -87,8 +86,7 @@ const generator: ImplementationGenerator = { depends_on: ['mysql_grant.user'], provisioner: { 'local-exec': { - command: - 'pkill -f "kubectl port-forward service/{{ HOST.dbms_name }}"', + command: `pkill -f "port-forward service/{{ HOST.dbms_name }}"`, interpreter: ['/bin/bash', '-c'], }, }, diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/remote-machine/ansible/index.ts index aeb8bee861..bf2a150e78 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/remote-machine/ansible/index.ts @@ -16,6 +16,20 @@ const generator: ImplementationGenerator = { reason: 'Primary use case due to the specialization of Ansible.', generate: (name, type) => { + const user = { + name: '{{ SELF.database_user }}', + password: '{{ SELF.database_password }}', + host: '%', + priv: '*.*:ALL', + } + + const login = { + login_host: '{{ HOST.application_address }}', + login_password: '{{ HOST.dbms_password }}', + login_port: '{{ HOST.application_port }}', + login_user: 'root', + } + return { derived_from: name, metadata: { @@ -56,23 +70,45 @@ const generator: ImplementationGenerator = { name: 'create database', 'community.mysql.mysql_db': { name: '{{ SELF.database_name }}', - login_host: '{{ HOST.application_address }}', - login_password: '{{ HOST.dbms_password }}', - login_port: '{{ HOST.application_port }}', - login_user: 'root', + ...login, }, }, { name: 'create user (with privileges)', 'community.mysql.mysql_user': { - name: '{{ SELF.database_user }}', - password: '{{ SELF.database_password }}', - host: '%', - priv: '*.*:ALL', - login_host: '{{ HOST.application_address }}', - login_password: '{{ HOST.dbms_password }}', - login_port: '{{ HOST.application_port }}', - login_user: 'root', + ...user, + ...login, + }, + }, + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, + delete: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + { + name: 'delete user (with privileges)', + 'community.mysql.mysql_user': { + state: 'absent', + ...user, + ...login, + }, + }, + { + name: 'delete database', + 'community.mysql.mysql_db': { + name: '{{ SELF.database_name }}', + state: 'absent', + ...login, }, }, ], @@ -80,7 +116,6 @@ const generator: ImplementationGenerator = { playbookArgs: [...AnsibleHostOperationPlaybookArgs()], }, }, - delete: 'exit 0', }, }, }, diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/index.ts index a6f4d21dc1..37846c4803 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/index.ts @@ -1,3 +1,3 @@ -import remoteMachine from './virtual-machine' +import remoteMachine from './remote-machine' export default [remoteMachine] diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/virtual-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/ansible/index.ts similarity index 74% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/virtual-machine/ansible/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/ansible/index.ts index 8fc5ae80f0..0a42711be3 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/virtual-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/ansible/index.ts @@ -74,7 +74,28 @@ const generator: ImplementationGenerator = { playbookArgs: [...AnsibleHostOperationPlaybookArgs()], }, }, - delete: 'exit 0', + delete: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + { + name: 'delete container', + 'community.docker.docker_container': { + name: '{{ SELF.dbms_name }}', + state: 'absent', + }, + }, + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, }, }, }, diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/virtual-machine/compose/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/compose/index.ts similarity index 52% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/virtual-machine/compose/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/compose/index.ts index 6dd097ca06..0b4683f6f7 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/virtual-machine/compose/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/compose/index.ts @@ -1,12 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleDockerHostEnvironment, AnsibleHostEndpointCapability, - AnsibleHostOperation, - AnsibleHostOperationPlaybookArgs, - AnsibleWaitForSSHTask, + AnsibleOrchestratorOperation, MetadataGenerated, MetadataUnfurl, - OpenstackMachineCredentials, + OpenstackMachineHost, } from '#technologies/plugins/rules/utils' const generator: ImplementationGenerator = { @@ -19,13 +18,46 @@ const generator: ImplementationGenerator = { details: 'docker-compose manifest generated and applied', generate: (name, type) => { + const AnsibleTouchComposeTask = { + name: 'touch compose', + register: 'compose', + 'ansible.builtin.tempfile': { + suffix: '{{ SELF.dbms_name }}.compose.yaml', + }, + } + + const AnsibleCreateComposeTask = { + name: 'create compose', + 'ansible.builtin.copy': { + dest: '{{ compose.path }}', + content: '{{ manifest | to_yaml }}', + }, + vars: { + manifest: { + name: '{{ SELF.dbms_name }}', + services: { + application: { + container_name: '{{ SELF.dbms_name }}', + image: 'mysql:{{ ".artifacts::dbms_image::file" | eval }}', + network_mode: 'host', + environment: { + MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password }}', + }, + }, + }, + }, + }, + } + return { derived_from: name, metadata: { ...MetadataGenerated(), ...MetadataUnfurl(), }, - properties: {...OpenstackMachineCredentials()}, + properties: { + ...OpenstackMachineHost(), + }, attributes: { application_address: { type: 'string', @@ -54,62 +86,56 @@ const generator: ImplementationGenerator = { operations: { create: { implementation: { - ...AnsibleHostOperation(), + ...AnsibleOrchestratorOperation(), }, inputs: { playbook: { q: [ - { - ...AnsibleWaitForSSHTask(), - }, - { - name: 'touch compose', - register: 'compose', - 'ansible.builtin.tempfile': { - suffix: '{{ SELF.dbms_name }}.compose.yaml', - }, - }, - { - name: 'create compose', - 'ansible.builtin.copy': { - dest: '{{ compose.path }}', - content: '{{ manifest | to_yaml }}', - }, - vars: { - manifest: { - name: '{{ SELF.dbms_name }}', - services: { - application: { - container_name: '{{ SELF.dbms_name }}', - image: 'mysql:{{ ".artifacts::dbms_image::file" | eval }}', - network_mode: 'host', - environment: { - MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password }}', - }, - }, - }, - }, - }, - }, + AnsibleTouchComposeTask, + AnsibleCreateComposeTask, { name: 'apply compose', 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', args: { executable: '/usr/bin/bash', }, + environment: { + ...AnsibleDockerHostEnvironment(), + }, }, { - name: 'give DBMS some time', + name: 'let it cook', 'ansible.builtin.pause': { seconds: 10, }, }, ], }, - playbookArgs: [...AnsibleHostOperationPlaybookArgs()], }, }, - delete: 'exit 0', + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + AnsibleTouchComposeTask, + AnsibleCreateComposeTask, + { + name: 'unapply compose', + 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', + args: { + executable: '/usr/bin/bash', + }, + environment: { + ...AnsibleDockerHostEnvironment(), + }, + }, + ], + }, + }, + }, }, }, }, diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/virtual-machine/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/virtual-machine/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/virtual-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/terraform/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/virtual-machine/terraform/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/terraform/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/ansible/index.ts index cc5b114360..d07b91269b 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/ansible/index.ts @@ -1,5 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleKubernetesCredentialsEnvironment, AnsibleOrchestratorOperation, KubernetesCredentials, MetadataGenerated, @@ -54,18 +55,7 @@ const generator: ImplementationGenerator = { implementation: { ...AnsibleOrchestratorOperation(), environment: { - K8S_AUTH_HOST: { - eval: '.::k8s_host', - }, - K8S_AUTH_SSL_CA_CERT: { - eval: '.::k8s_ca_cert_file', - }, - K8S_AUTH_CERT_FILE: { - eval: '.::k8s_client_cert_file', - }, - K8S_AUTH_KEY_FILE: { - eval: '.::k8s_client_key_file', - }, + ...AnsibleKubernetesCredentialsEnvironment(), }, }, inputs: { @@ -149,7 +139,40 @@ const generator: ImplementationGenerator = { }, }, }, - delete: 'exit 0', + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + environment: { + ...AnsibleKubernetesCredentialsEnvironment(), + }, + }, + inputs: { + playbook: { + q: [ + { + name: 'delete service', + 'kubernetes.core.k8s': { + state: 'absent', + api_version: 'v1', + kind: 'Service', + name: '{{ SELF.dbms_name }}', + namespace: 'default', + }, + }, + { + name: 'delete deployment', + 'kubernetes.core.k8s': { + state: 'absent', + api_version: 'apps/v1', + kind: 'Deployment', + name: '{{ SELF.dbms_name }}', + namespace: 'default', + }, + }, + ], + }, + }, + }, }, }, }, diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/kubernetes/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/kubernetes/index.ts index 9b30cba97c..725d609889 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/kubernetes/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/kubernetes/index.ts @@ -1,13 +1,12 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleOrchestratorOperation, + BASH_KUBECTL, KubernetesCredentials, MetadataGenerated, MetadataUnfurl, } from '#technologies/plugins/rules/utils' -// TODO: does not use k8s auth - const generator: ImplementationGenerator = { component: 'mysql.dbms', technology: 'kubernetes', @@ -18,6 +17,86 @@ const generator: ImplementationGenerator = { details: 'Kubernetes manifest generated and applied', generate: (name, type) => { + const AnsibleTouchManifestTask = { + name: 'touch manifest', + register: 'manifest', + 'ansible.builtin.tempfile': { + suffix: '{{ SELF.dbms_name }}.dbms.manifest.yaml', + }, + } + + const AnsibleCreateMainfestTask = { + name: 'create manifest', + 'ansible.builtin.copy': { + dest: '{{ manifest.path }}', + content: '{{ deployment | to_yaml }}\n---\n{{ service | to_yaml }}\n', + }, + vars: { + deployment: { + apiVersion: 'apps/v1', + kind: 'Deployment', + metadata: { + name: '{{ SELF.dbms_name }}', + namespace: 'default', + }, + spec: { + selector: { + matchLabels: { + app: '{{ SELF.dbms_name }}', + }, + }, + template: { + metadata: { + labels: { + app: '{{ SELF.dbms_name }}', + }, + }, + spec: { + containers: [ + { + image: 'mysql:{{ ".artifacts::dbms_image::file" | eval }}', + name: '{{ SELF.dbms_name }}', + env: [ + { + name: 'MYSQL_ROOT_PASSWORD', + value: '{{ SELF.dbms_password }}', + }, + ], + ports: [ + { + containerPort: 3306, + name: 'mysql', + }, + ], + }, + ], + }, + }, + }, + }, + service: { + apiVersion: 'v1', + kind: 'Service', + metadata: { + name: '{{ SELF.dbms_name }}', + }, + spec: { + ports: [ + { + name: 'mysql', + port: 3306, + targetPort: 3306, + }, + ], + selector: { + app: '{{ SELF.dbms_name }}', + }, + type: 'ClusterIP', + }, + }, + }, + } + return { derived_from: name, metadata: { @@ -59,101 +138,24 @@ const generator: ImplementationGenerator = { inputs: { playbook: { q: [ - { - name: 'touch manifest', - register: 'manifest', - 'ansible.builtin.tempfile': { - suffix: '{{ SELF.dbms_name }}.dbms.manifest.yaml', - }, - }, - { - name: 'create manifest', - 'ansible.builtin.copy': { - dest: '{{ manifest.path }}', - content: '{{ deployment | to_yaml }}\n---\n{{ service | to_yaml }}\n', - }, - vars: { - deployment: { - apiVersion: 'apps/v1', - kind: 'Deployment', - metadata: { - name: '{{ SELF.dbms_name }}', - namespace: 'default', - }, - spec: { - selector: { - matchLabels: { - app: '{{ SELF.dbms_name }}', - }, - }, - template: { - metadata: { - labels: { - app: '{{ SELF.dbms_name }}', - }, - }, - spec: { - containers: [ - { - image: 'mysql:{{ ".artifacts::dbms_image::file" | eval }}', - name: '{{ SELF.dbms_name }}', - env: [ - { - name: 'MYSQL_ROOT_PASSWORD', - value: '{{ SELF.dbms_password }}', - }, - ], - ports: [ - { - containerPort: 3306, - name: 'mysql', - }, - ], - }, - ], - }, - }, - }, - }, - service: { - apiVersion: 'v1', - kind: 'Service', - metadata: { - name: '{{ SELF.dbms_name }}', - }, - spec: { - ports: [ - { - name: 'mysql', - port: 3306, - targetPort: 3306, - }, - ], - selector: { - app: '{{ SELF.dbms_name }}', - }, - type: 'ClusterIP', - }, - }, - }, - }, + AnsibleTouchManifestTask, + AnsibleCreateMainfestTask, { name: 'apply manifest', - 'ansible.builtin.shell': 'kubectl apply -f {{ manifest.path }}', + 'ansible.builtin.shell': `${BASH_KUBECTL} apply -f {{ manifest.path }}`, args: { executable: '/usr/bin/bash', }, }, { name: 'wait for deployment', - 'ansible.builtin.shell': - 'kubectl rollout status deployment/{{ SELF.dbms_name }} --timeout 60s', + 'ansible.builtin.shell': `${BASH_KUBECTL} rollout status deployment/{{ SELF.dbms_name }} --timeout 60s`, args: { executable: '/usr/bin/bash', }, }, { - name: 'give DBMS some time', + name: 'let it cook', 'ansible.builtin.pause': { seconds: 10, }, @@ -162,7 +164,26 @@ const generator: ImplementationGenerator = { }, }, }, - delete: 'exit 0', + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + AnsibleTouchManifestTask, + AnsibleCreateMainfestTask, + { + name: 'unapply manifest', + 'ansible.builtin.shell': `${BASH_KUBECTL} delete -f {{ manifest.path }}`, + args: { + executable: '/usr/bin/bash', + }, + }, + ], + }, + }, + }, }, }, }, diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/ansible/index.ts index 309d9c3a62..e5553f7616 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/ansible/index.ts @@ -76,21 +76,20 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - name: 'Installing mysql', + name: 'installing mysql', 'ansible.builtin.apt': { - name: '{{ item }}', + name: [ + 'mysql-server', + 'mysql-client', + 'python3-mysqldb', + 'libmysqlclient-dev', + ], state: 'present', update_cache: 'yes', }, - loop: [ - 'mysql-server', - 'mysql-client', - 'python3-mysqldb', - 'libmysqlclient-dev', - ], }, { - name: 'Start and enable mysql service', + name: 'start and enable mysql service', 'ansible.builtin.systemd': { name: 'mysql', state: 'started', @@ -98,7 +97,7 @@ const generator: ImplementationGenerator = { }, }, { - name: 'Enable passwordless login', + name: 'enable passwordless login', 'ansible.builtin.copy': { dest: '{{ item }}', content: files.toINI({ @@ -111,7 +110,7 @@ const generator: ImplementationGenerator = { loop: ['/root/.my.cnf', '/home/{{ SELF.os_ssh_user }}/.my.cnf'], }, { - name: 'Configure port (e.g., since 3306 is blocked by the provider)', + name: 'configure port (e.g., since 3306 is blocked by the provider)', 'ansible.builtin.lineinfile': { path: '/etc/mysql/mysql.conf.d/mysqld.cnf', regexp: '^# port', @@ -120,7 +119,7 @@ const generator: ImplementationGenerator = { }, }, { - name: 'Enable remote login', + name: 'enable remote login', 'ansible.builtin.lineinfile': { path: '/etc/mysql/mysql.conf.d/mysqld.cnf', regexp: '^bind-address', @@ -129,14 +128,14 @@ const generator: ImplementationGenerator = { }, }, { - name: 'Restart mysql', + name: 'restart mysql', 'ansible.builtin.systemd': { name: 'mysql', state: 'restarted', }, }, { - name: 'Create all root', + name: 'create all root', 'community.mysql.mysql_user': { name: 'root', password: '{{ SELF.dbms_password }}', @@ -150,7 +149,7 @@ const generator: ImplementationGenerator = { }, }, { - name: 'Delete localhost root', + name: 'delete localhost root', 'community.mysql.mysql_user': { name: 'root', host: 'localhost', @@ -166,7 +165,41 @@ const generator: ImplementationGenerator = { playbookArgs: [...AnsibleHostOperationPlaybookArgs()], }, }, - delete: 'exit 0', + delete: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + { + name: 'uninstalling mysql', + 'ansible.builtin.apt': { + name: [ + 'mysql-server', + 'mysql-client', + 'python3-mysqldb', + 'libmysqlclient-dev', + ], + state: 'absent', + }, + }, + { + name: 'remove passwordless login', + 'ansible.builtin.file': { + name: '{{ item }}', + state: 'absent', + }, + loop: ['/root/.my.cnf', '/home/{{ SELF.os_ssh_user }}/.my.cnf'], + }, + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, }, }, }, diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/remote-machine/ansible/index.ts index 3389e62deb..3538970d79 100644 --- a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/remote-machine/ansible/index.ts @@ -59,7 +59,28 @@ const generator: ImplementationGenerator = { playbookArgs: [...AnsibleHostOperationPlaybookArgs()], }, }, - delete: 'exit 0', + delete: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + { + name: 'stop container', + 'community.docker.docker_container': { + name: '{{ SELF.application_name }}', + state: 'absent', + }, + }, + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, }, }, }, diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/remote-machine/compose/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/remote-machine/compose/index.ts index f5e3a4d010..68d7b267b3 100644 --- a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/remote-machine/compose/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/remote-machine/compose/index.ts @@ -1,16 +1,13 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { - AnsibleHostOperation, - AnsibleHostOperationPlaybookArgs, - AnsibleWaitForSSHTask, + AnsibleDockerHostEnvironment, + AnsibleOrchestratorOperation, MetadataGenerated, MetadataUnfurl, - OpenstackMachineCredentials, + OpenstackMachineHost, mapProperties, } from '#technologies/plugins/rules/utils' -// TODO: it must connect via DOCKER_HOST ssh and not via Ansible?! - const generator: ImplementationGenerator = { component: 'service.application', technology: 'compose', @@ -21,13 +18,44 @@ const generator: ImplementationGenerator = { details: 'docker compose manifest generated and applied', generate: (name, type) => { + const AnsibleTouchComposeTask = { + name: 'touch compose', + register: 'compose', + 'ansible.builtin.tempfile': { + suffix: '{{ SELF.application_name }}.compose.yaml', + }, + } + + const AnsibleCreateComposeTask = { + name: 'create compose', + 'ansible.builtin.copy': { + dest: '{{ compose.path }}', + content: '{{ manifest | to_yaml }}', + }, + vars: { + manifest: { + name: '{{ SELF.application_name }}', + services: { + application: { + container_name: '{{ SELF.application_name }}', + image: '{{ ".artifacts::docker_image::file" | eval }}', + network_mode: 'host', + environment: mapProperties(type, {format: 'map'}), + }, + }, + }, + }, + } + return { derived_from: name, metadata: { ...MetadataGenerated(), ...MetadataUnfurl(), }, - properties: {...OpenstackMachineCredentials()}, + properties: { + ...OpenstackMachineHost(), + }, attributes: { application_address: { type: 'string', @@ -39,54 +67,50 @@ const generator: ImplementationGenerator = { operations: { create: { implementation: { - ...AnsibleHostOperation(), + ...AnsibleOrchestratorOperation(), }, inputs: { playbook: { q: [ + AnsibleTouchComposeTask, + AnsibleCreateComposeTask, { - ...AnsibleWaitForSSHTask(), - }, - { - name: 'touch compose', - register: 'compose', - 'ansible.builtin.tempfile': { - suffix: '{{ SELF.application_name }}.compose.yaml', - }, - }, - { - name: 'create compose', - 'ansible.builtin.copy': { - dest: '{{ compose.path }}', - content: '{{ manifest | to_yaml }}', + name: 'apply compose', + 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', + args: { + executable: '/usr/bin/bash', }, - vars: { - manifest: { - name: '{{ SELF.application_name }}', - services: { - application: { - container_name: '{{ SELF.application_name }}', - image: '{{ ".artifacts::docker_image::file" | eval }}', - network_mode: 'host', - environment: mapProperties(type, {format: 'map'}), - }, - }, - }, + environment: { + ...AnsibleDockerHostEnvironment(), }, }, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + AnsibleTouchComposeTask, + AnsibleCreateComposeTask, { name: 'apply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', + 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', args: { executable: '/usr/bin/bash', }, + environment: { + ...AnsibleDockerHostEnvironment(), + }, }, ], }, - playbookArgs: [...AnsibleHostOperationPlaybookArgs()], }, }, - delete: 'exit 0', }, }, }, diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/kubernetes-cluster/ansible/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/kubernetes-cluster/ansible/index.ts index ef567d4cab..ebd88977ae 100644 --- a/src/technologies/plugins/rules/generators/service-application/docker-image/kubernetes-cluster/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/kubernetes-cluster/ansible/index.ts @@ -1,5 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleKubernetesCredentialsEnvironment, AnsibleOrchestratorOperation, KubernetesCredentials, MetadataGenerated, @@ -39,18 +40,7 @@ const generator: ImplementationGenerator = { implementation: { ...AnsibleOrchestratorOperation(), environment: { - K8S_AUTH_HOST: { - eval: '.::k8s_host', - }, - K8S_AUTH_SSL_CA_CERT: { - eval: '.::k8s_ca_cert_file', - }, - K8S_AUTH_CERT_FILE: { - eval: '.::k8s_client_cert_file', - }, - K8S_AUTH_KEY_FILE: { - eval: '.::k8s_client_key_file', - }, + ...AnsibleKubernetesCredentialsEnvironment(), }, }, inputs: { @@ -129,7 +119,40 @@ const generator: ImplementationGenerator = { }, }, }, - delete: 'exit 0', + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + environment: { + ...AnsibleKubernetesCredentialsEnvironment(), + }, + }, + inputs: { + playbook: { + q: [ + { + name: 'delete service', + 'kubernetes.core.k8s': { + state: 'absent', + api_version: 'v1', + kind: 'Service', + namespace: 'default', + name: '{{ SELF.application_name }}', + }, + }, + { + name: 'delete deployment', + 'kubernetes.core.k8s': { + state: 'absent', + api_version: 'app/v1', + kind: 'Deployment', + namespace: 'default', + name: '{{ SELF.application_name }}', + }, + }, + ], + }, + }, + }, }, }, }, diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/kubernetes-cluster/kubernetes/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/kubernetes-cluster/kubernetes/index.ts index 3f7ee9b216..c34d9b71de 100644 --- a/src/technologies/plugins/rules/generators/service-application/docker-image/kubernetes-cluster/kubernetes/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/kubernetes-cluster/kubernetes/index.ts @@ -1,13 +1,12 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleOrchestratorOperation, + BASH_KUBECTL, MetadataGenerated, MetadataUnfurl, mapProperties, } from '#technologies/plugins/rules/utils' -// TODO: does not use k8s auth - const generator: ImplementationGenerator = { component: 'service.application', technology: 'kubernetes', @@ -18,6 +17,81 @@ const generator: ImplementationGenerator = { details: 'Kubernetes manifest generated and applied', generate: (name, type) => { + const AnsibleTouchManifestTask = { + name: 'touch manifest', + register: 'manifest', + 'ansible.builtin.tempfile': { + suffix: '{{ SELF.application_name }}.application.manifest.yaml', + }, + } + + const AnsibleCreateManifestTak = { + name: 'create manifest', + 'ansible.builtin.copy': { + dest: '{{ manifest.path }}', + content: '{{ deployment | to_yaml }}\n---\n{{ service | to_yaml }}\n', + }, + vars: { + deployment: { + apiVersion: 'apps/v1', + kind: 'Deployment', + metadata: { + name: '{{ SELF.application_name }}', + namespace: 'default', + }, + spec: { + selector: { + matchLabels: { + app: '{{ SELF.application_name }}', + }, + }, + template: { + metadata: { + labels: { + app: '{{ SELF.application_name }}', + }, + }, + spec: { + containers: [ + { + image: '{{ ".artifacts::docker_image::file" | eval }}', + name: '{{ SELF.application_name }}', + env: mapProperties(type), + ports: [ + { + containerPort: '{{ SELF.application_port }}', + }, + ], + }, + ], + }, + }, + }, + }, + service: { + apiVersion: 'v1', + kind: 'Service', + metadata: { + name: '{{ SELF.application_name }}', + namespace: 'default', + }, + spec: { + ports: [ + { + name: '{{ SELF.application_protocol }}', + port: '{{ SELF.application_port }}', + targetPort: '{{ SELF.application_port }}', + }, + ], + selector: { + app: '{{ SELF.application_name }}', + }, + type: 'ClusterIP', + }, + }, + }, + } + return { derived_from: name, metadata: { @@ -42,91 +116,38 @@ const generator: ImplementationGenerator = { inputs: { playbook: { q: [ + AnsibleTouchManifestTask, + AnsibleCreateManifestTak, { - name: 'touch manifest', - register: 'manifest', - 'ansible.builtin.tempfile': { - suffix: '{{ SELF.application_name }}.application.manifest.yaml', - }, - }, - { - name: 'create manifest', - 'ansible.builtin.copy': { - dest: '{{ manifest.path }}', - content: '{{ deployment | to_yaml }}\n---\n{{ service | to_yaml }}\n', - }, - vars: { - deployment: { - apiVersion: 'apps/v1', - kind: 'Deployment', - metadata: { - name: '{{ SELF.application_name }}', - namespace: 'default', - }, - spec: { - selector: { - matchLabels: { - app: '{{ SELF.application_name }}', - }, - }, - template: { - metadata: { - labels: { - app: '{{ SELF.application_name }}', - }, - }, - spec: { - containers: [ - { - image: '{{ ".artifacts::docker_image::file" | eval }}', - name: '{{ SELF.application_name }}', - env: mapProperties(type), - ports: [ - { - containerPort: - '{{ SELF.application_port }}', - }, - ], - }, - ], - }, - }, - }, - }, - service: { - apiVersion: 'v1', - kind: 'Service', - metadata: { - name: '{{ SELF.application_name }}', - namespace: 'default', - }, - spec: { - ports: [ - { - name: '{{ SELF.application_protocol }}', - port: '{{ SELF.application_port }}', - targetPort: '{{ SELF.application_port }}', - }, - ], - selector: { - app: '{{ SELF.application_name }}', - }, - type: 'ClusterIP', - }, - }, + name: 'apply manifest', + 'ansible.builtin.shell': `${BASH_KUBECTL} apply -f {{ manifest.path }}`, + args: { + executable: '/usr/bin/bash', }, }, { - name: 'apply manifest', - 'ansible.builtin.shell': 'kubectl apply -f {{ manifest.path }}', + name: 'wait for deployment', + 'ansible.builtin.shell': `${BASH_KUBECTL} rollout status deployment/{{ SELF.application_name }} --timeout 60s`, args: { executable: '/usr/bin/bash', }, }, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + AnsibleTouchManifestTask, + AnsibleCreateManifestTak, { - name: 'wait for deployment', - 'ansible.builtin.shell': - 'kubectl rollout status deployment/{{ SELF.application_name }} --timeout 60s', + name: 'unapply manifest', + 'ansible.builtin.shell': `${BASH_KUBECTL} delete -f {{ manifest.path }}`, args: { executable: '/usr/bin/bash', }, @@ -135,7 +156,6 @@ const generator: ImplementationGenerator = { }, }, }, - delete: 'exit 0', }, }, }, diff --git a/src/technologies/plugins/rules/utils.ts b/src/technologies/plugins/rules/utils.ts index 91f2dac115..202d13321c 100644 --- a/src/technologies/plugins/rules/utils.ts +++ b/src/technologies/plugins/rules/utils.ts @@ -204,6 +204,9 @@ export function KubernetesCredentials() { } } +export const BASH_KUBECTL = + 'kubectl --server {{ SELF.k8s_host }} --certificate-authority {{ SELF.k8s_ca_cert_file }} --client-certificate {{ SELF.k8s_client_cert_file }} --client-key {{ SELF.k8s_client_key_file }}' + export function AnsibleHostEndpointCapability() { return { endpoint: { @@ -233,6 +236,29 @@ export function AnsibleOrchestratorOperation() { } } +export function AnsibleKubernetesCredentialsEnvironment() { + return { + K8S_AUTH_HOST: { + eval: '.::k8s_host', + }, + K8S_AUTH_SSL_CA_CERT: { + eval: '.::k8s_ca_cert_file', + }, + K8S_AUTH_CERT_FILE: { + eval: '.::k8s_client_cert_file', + }, + K8S_AUTH_KEY_FILE: { + eval: '.::k8s_client_key_file', + }, + } +} + +export function AnsibleDockerHostEnvironment() { + return { + DOCKER_HOST: '{{ SELF.os_ssh_host }}', + } +} + export function AnsibleHostOperationPlaybookArgs() { return ['--become', '--key-file={{ SELF.os_ssh_key_file }}', '--user={{ SELF.os_ssh_user }}'] } diff --git a/src/utils/files.ts b/src/utils/files.ts index 7b2bb76bb2..040fe0bbbb 100644 --- a/src/utils/files.ts +++ b/src/utils/files.ts @@ -9,7 +9,7 @@ import * as ejs from 'ejs' import extract from 'extract-zip' import * as fss from 'fs' import * as fse from 'fs-extra' -import * as ini from 'ini' +import * as ini from 'js-ini' import * as yaml from 'js-yaml' import lnk from 'lnk' import _ from 'lodash' @@ -216,7 +216,7 @@ export function toENV(obj: {[key: string]: string | number | boolean}, options: } export function toINI(obj: any) { - return ini.stringify(obj, {platform: 'linux'}) + return utils.trim(ini.stringify(obj)) } export function copy(source: string, target: string, options: {overwrite?: boolean} = {}) { diff --git a/src/utils/utils.ts b/src/utils/utils.ts index aaa6e31a5b..bd557740ba 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -217,10 +217,14 @@ export function replace(data: string, entries: [find: string, replace: string][] return data } -export function indent(str: string, spaces = 4) { +export function indent(value: string, spaces = 4) { const padding = ' '.repeat(spaces) - return str + return value .split('\n') .map(line => padding + line) .join('\n') } + +export function trim(value: string): string { + return value.trim() + `\n` +} diff --git a/yarn.lock b/yarn.lock index 5bccea6ff8..8af61ce156 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3865,13 +3865,6 @@ __metadata: languageName: node linkType: hard -"ini@npm:^4.1.3": - version: 4.1.3 - resolution: "ini@npm:4.1.3" - checksum: 004b2be42388877c58add606149f1a0c7985c90a0ba5dbf45a4738fdc70b0798d922caecaa54617029626505898ac451ff0537a08b949836b49d3267f66542c9 - languageName: node - linkType: hard - "ini@npm:~1.3.0": version: 1.3.8 resolution: "ini@npm:1.3.8" @@ -4363,6 +4356,13 @@ __metadata: languageName: node linkType: hard +"js-ini@npm:^1.6.0": + version: 1.6.0 + resolution: "js-ini@npm:1.6.0" + checksum: 84392889ee4c97574747b37a49ecb69705df8ab28d74710e5819c59246d6f7086ced24b899198e71ff3a748abe8655cc399367952ea3ce72b0e38bfdf4665b13 + languageName: node + linkType: hard + "js-sdsl@npm:^4.1.4": version: 4.4.0 resolution: "js-sdsl@npm:4.4.0" @@ -5606,8 +5606,8 @@ __metadata: fs-extra: ^11.2.0 glob: ^10.4.1 http-errors: ^2.0.0 - ini: ^4.1.3 is-wsl: ^2.2.0 + js-ini: ^1.6.0 js-yaml: ^4.1.0 json-diff: ^1.0.6 license-checker: ^25.0.1