From a67d1779b1a849c7169d3487ce58b7b097410758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Fri, 6 Sep 2024 12:21:44 +0200 Subject: [PATCH 01/18] technology industry --- .../lib/retailer.yaml | 35 + .../lib/rules.yaml | 365 ++++++++ .../lib/tosca-vintner-profile-core.yaml | 358 ++++++++ .../lib/tosca-vintner-profile-extended.yaml | 470 ++++++++++ .../lib/tosca-vintner-profile.yaml | 21 + .../lib/types.yaml | 4 + .../scripts/clean.sh | 11 + .../scripts/code.sh | 11 + .../scripts/configuration.env | 5 + .../scripts/configuration.sh | 36 + .../scripts/continue.sh | 11 + .../scripts/deploy.sh | 16 + .../scripts/enrich.sh | 8 + .../scripts/implement.sh | 8 + .../scripts/pull.sh | 9 + .../scripts/quality.sh | 13 + .../scripts/reimport.sh | 20 + .../scripts/setup.sh | 14 + .../scripts/study-001.txt | 107 +++ .../scripts/study-002.txt | 106 +++ .../scripts/study-003.txt | 106 +++ .../scripts/study-004.txt | 106 +++ .../scripts/study-005.txt | 107 +++ .../scripts/study-006.txt | 107 +++ .../scripts/study-007.txt | 116 +++ .../scripts/study.sh | 8 + .../scripts/swap-lib.sh | 16 + .../scripts/undeploy.sh | 11 + .../scripts/unimplement.sh | 9 + .../study.yaml | 6 + .../tests/gcp/expected.yaml | 310 +++++++ .../tests/gcp/inputs.yaml | 1 + .../tests/gcp/test.yaml | 21 + .../tests/kubernetes/expected.yaml | 340 +++++++ .../tests/kubernetes/inputs.yaml | 1 + .../tests/os-large/expected.yaml | 402 +++++++++ .../tests/os-large/inputs.yaml | 2 + .../tests/os-large/test.yaml | 21 + .../tests/os-medium/expected.yaml | 402 +++++++++ .../tests/os-medium/inputs.yaml | 2 + .../tests/os-medium/test.yaml | 21 + .../variable-service-template.yaml | 852 ++++++++++++++++++ src/normative/types/core/nodes.ts | 53 ++ src/normative/types/extended/nodes.ts | 44 + 44 files changed, 4692 insertions(+) create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/lib/retailer.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/lib/types.yaml create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/clean.sh create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/code.sh create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.env create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.sh create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/continue.sh create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/deploy.sh create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/enrich.sh create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/implement.sh create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/pull.sh create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/reimport.sh create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/setup.sh create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-001.txt create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-002.txt create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-003.txt create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-004.txt create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-005.txt create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-006.txt create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-007.txt create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study.sh create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/swap-lib.sh create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/undeploy.sh create mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/unimplement.sh create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/study.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/expected.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/inputs.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/test.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/expected.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/inputs.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/expected.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/inputs.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/test.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/expected.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/inputs.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/test.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/retailer.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/retailer.yaml new file mode 100644 index 0000000000..f14f4d9919 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/retailer.yaml @@ -0,0 +1,35 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - ../tosca-vintner-profile.yaml + +node_types: + retailer.frontend.dashboard: + derived_from: reactjs.service.application + + retailer.frontend.terminal: + derived_from: reactjs.service.application + + retailer.service.gateway: + derived_from: nodejs.service.application + + retailer.service.core: + derived_from: nodejs.service.application + + retailer.service.jobs: + derived_from: nodejs.service.application + + retailer.service.stores: + derived_from: nodejs.service.application + + retailer.service.products: + derived_from: nodejs.service.application + + retailer.service.stocks: + derived_from: nodejs.service.application + + retailer.service.orders: + derived_from: nodejs.service.application + + retailer.service.global: + derived_from: nodejs.service.application diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml new file mode 100644 index 0000000000..6f279bd251 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml @@ -0,0 +1,365 @@ +################################################### +# +# WARNING: Do not edit! This file is autogenerated! +# +################################################### + +ansible: + - component: docker.engine + hosting: + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks' + - component: gcp.service + hosting: [] + weight: 1 + reason: Ansible provides a declarative module + details: '"google.cloud.gcp_serviceusage_service" task' + - component: ingress + hosting: + - kubernetes.cluster + weight: 0.5 + reason: Kubernetes is more specialized. + details: '"kubernetes.core.k8s" task' + - component: ingress + hosting: + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", "ansible.builtin.copy", and "ansible.builtin.systemd" tasks' + - component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + - component: mysql.database + hosting: + - mysql.dbms + - gcp.cloudsql + weight: 0.5 + reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. + - component: mysql.database + hosting: + - mysql.dbms + - kubernetes.cluster + weight: 1 + reason: Primary use case due to the specialization of Ansible. + - component: mysql.database + hosting: + - mysql.dbms + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + - component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized + details: '"community.docker.docker_container" task' + - component: mysql.dbms + artifact: dbms.image + hosting: + - gcp.cloudsql + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"google.cloud.gcp_sql_instance" and "google.cloud.gcp_sql_user" tasks' + - component: mysql.dbms + artifact: dbms.image + hosting: + - kubernetes.cluster + weight: 0.5 + reason: Kubernetes is more specialized. + details: '"kubernetes.core.k8s" tasks' + - component: mysql.dbms + artifact: dbms.image + hosting: + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks' + - component: service.application + artifact: docker.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"community.docker.docker_container" task' + - component: service.application + artifact: docker.image + hosting: + - gcp.cloudrun + weight: 0 + reason: Custom module with imperative parts, while Terraform provides a declarative module. + details: '"ansible.builtin.shell", "ansible.builtin.tempfile", and "ansible.builtin.copy" tasks ' + - component: service.application + artifact: docker.image + hosting: + - kubernetes.cluster + weight: 0.5 + reason: Kubernetes is more specialized. + details: '"kubernetes.core.k8s" tasks' + - component: service.application + artifact: tar.archive + hosting: + - '*' + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. Special integration for systemd. + details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements' + - component: service.application + artifact: zip.archive + hosting: + - '*' + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. Special integration for systemd. + details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements' + - component: service.application + artifact: zip.archive + hosting: + - gcp.appengine + weight: 0 + reason: Custom module with imperative parts, while Terraform provides a declarative module. + details: '"ansible.builtin.shell", "ansible.builtin.tempfile", "ansible.builtin.unarchive", and "ansible.builtin.copy" tasks' + - component: software.application + artifact: apt.package + hosting: + - '*' + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements' + - component: software.application + artifact: tar.archive + hosting: + - '*' + - remote.machine + weight: 0.5 + reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application". + details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' + - component: software.application + artifact: zip.archive + hosting: + - '*' + - remote.machine + weight: 0.5 + reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. + details: '"ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' + - component: virtual.machine + artifact: machine.image + hosting: + - openstack.provider + weight: 0.5 + reason: Terraform is more specialized. + details: '"openstack.cloud.security_group", "openstack.cloud.security_group_rule" and "openstack.cloud.server" tasks' +terraform: + - component: docker.engine + hosting: + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"remote-exec" provider' + - component: gcp.service + hosting: [] + weight: 1 + reason: Terraform provides a declarative module. + details: '"google_project_service" resource' + - component: ingress + hosting: + - kubernetes.cluster + weight: 0.5 + reason: Kubernetes is more specialized. + details: '"kubernetes_service_v1" resource' + - component: ingress + hosting: + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' + - component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - remote.machine + weight: 0.5 + reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. + - component: mysql.database + hosting: + - mysql.dbms + - gcp.cloudsql + weight: 1 + reason: Terraform provides a declarative module. + - component: mysql.database + hosting: + - mysql.dbms + - kubernetes.cluster + weight: 0 + reason: Ansible is more specialized. + - component: mysql.database + hosting: + - mysql.dbms + - remote.machine + weight: 0.5 + reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. + - component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' + - component: mysql.dbms + artifact: dbms.image + hosting: + - gcp.cloudsql + weight: 1 + reason: Terraform provides a declarative module. + details: '"google_sql_database_instance" and "google_sql_user" resources' + - component: mysql.dbms + artifact: dbms.image + hosting: + - kubernetes.cluster + weight: 0.5 + reason: Kubernetes is more specialized. + details: '"kubernetes_deployment_v1" and "kubernetes_service_v1" resources' + - component: mysql.dbms + artifact: dbms.image + hosting: + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' + - component: service.application + artifact: docker.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' + - component: service.application + artifact: docker.image + hosting: + - gcp.cloudrun + weight: 1 + reason: Terraform provides a declarative module. + details: '"google_cloud_run_v2_service" and "google_cloud_run_service_iam_binding" resources' + - component: service.application + artifact: docker.image + hosting: + - kubernetes.cluster + weight: 0.5 + reason: Kubernetes is more specialized. + details: '"kubernetes_deployment_v1" and "kubernetes_service_v1" resources' + - component: service.application + artifact: tar.archive + hosting: + - '*' + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' + - component: service.application + artifact: zip.archive + hosting: + - '*' + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' + - component: service.application + artifact: zip.archive + hosting: + - gcp.appengine + weight: 1 + reason: Terraform provides a declarative module. + details: '"google_app_engine_standard_app_version", "google_project_iam_member", "google_service_account", "google_storage_bucket", and "google_storage_bucket_object" resources' + - component: software.application + artifact: apt.archive + hosting: + - '*' + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"file" provisioner to upload scripts and "remote-exec" to execute scripts' + - component: software.application + artifact: tar.archive + hosting: + - '*' + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' + - component: software.application + artifact: zip.archive + hosting: + - '*' + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' + - component: virtual.machine + artifact: machine.image + hosting: + - openstack.provider + weight: 1 + reason: Terraform provides a declarative module. + details: '"openstack_compute_instance_v2", "openstack_networking_secgroup_rule_v2" and "openstack_networking_secgroup_v2" resources' +kubernetes: + - component: ingress + hosting: + - kubernetes.cluster + weight: 1 + reason: Kubernetes is the underlying technology. + details: Kubernetes manifest generated and applied + - component: mysql.database + hosting: + - mysql.dbms + - kubernetes.cluster + weight: 0 + reason: Kubernetes Job with imperative parts, while declarative other technologies provide declarative modules. + - component: mysql.dbms + artifact: dbms.image + hosting: + - kubernetes.cluster + weight: 1 + reason: Kubernetes is the underlying technology. + details: Kubernetes manifest generated and applied + - component: service.application + artifact: docker.image + hosting: + - kubernetes.cluster + weight: 1 + reason: Kubernetes is the underlying technology. + details: Kubernetes manifest generated and applied +compose: + - component: mysql.database + 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. + - component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - remote.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker-compose manifest generated and applied + - component: service.application + artifact: docker.image + hosting: + - docker.engine + - remote.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker compose manifest generated and applied diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml new file mode 100644 index 0000000000..5fdd64d120 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml @@ -0,0 +1,358 @@ +################################################### +# +# WARNING: Do not edit! This file is autogenerated! +# +################################################### + +tosca_definitions_version: tosca_simple_yaml_1_3 +description: TOSCA Profile for OpenTOSCA Vintner (Core) +metadata: + vintner_normative: 'true' + template_name: TOSCA Vintner Profile (Core) + template_author: Miles Stötzner + template_contact: miles.stoetzner@iste.uni-stuttgart.de + template_link: https://vintner.opentosca.org + template_version: 1.0.0-draft + template_id: tosca-vintner-profile + template_license: https://www.apache.org/licenses/LICENSE-2.0 + acknowledgments: Partially funded by the [German Federal Ministry for Economic Affairs and Climate Action (BMWK)](https://www.bmwk.de) as part of the research project [SofDCar (19S21002)](https://sofdcar.de). + vintner_orchestrator: unfurl +artifact_types: + artifact: + derived_from: tosca.artifacts.Root + source.archive: + derived_from: artifact + description: application packaged as archive + properties: + extra_opts: + type: list + entry_schema: + type: string + required: false + default: [] + system.package: + derived_from: artifact + properties: + script: + type: string + required: false + description: URL of an installation script + default: '' + repository: + type: string + required: false + description: name of the repository (required if source is set) + default: '' + key: + type: string + required: false + description: URL of the apt key which signs the apt repository (required if source is set) + default: '' + source: + type: string + required: false + description: source of the repository + default: '' + dependencies: + type: string + required: false + description: Comma separated list of apt packages that are additionally installed + default: '' + env: + type: string + required: false + description: Space separated env variables + default: '' + container.image: + derived_from: artifact + description: expects image reference in "file" + machine.image: + derived_from: artifact + description: expects image reference in "file" + dbms.image: + derived_from: artifact + description: expects image reference in "file" +interface_types: + interface: + derived_from: tosca.interfaces.Root + metadata: + vintner_normative: 'true' + management: + derived_from: interface + metadata: + vintner_normative: 'true' + operations: + create: + description: management lifecycle create operation. + configure: + description: management lifecycle configure operation. + start: + description: management lifecycle start operation. + stop: + description: management lifecycle stop operation. + delete: + description: management lifecycle delete operation. +node_types: + node: + derived_from: tosca.nodes.Root + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + cloud.provider: + derived_from: node + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + capabilities: + host: + type: tosca.capabilities.Compute + cloud.service: + derived_from: node + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + capabilities: + host: + type: tosca.capabilities.Compute + requirements: + - host: + capability: tosca.capabilities.Compute + relationship: tosca.relationships.HostedOn + software.application: + derived_from: node + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + application_name: + type: string + _management_create: + type: string + metadata: + vintner_ignore: 'true' + default: + eval: + python: '{{ "project" | get_dir }}/vintner_utils.py#get_operation' + args: + - management + - create + _management_configure: + type: string + metadata: + vintner_ignore: 'true' + default: + eval: + python: '{{ "project" | get_dir }}/vintner_utils.py#get_operation' + args: + - management + - configure + _management_start: + type: string + metadata: + vintner_ignore: 'true' + default: + eval: + python: '{{ "project" | get_dir }}/vintner_utils.py#get_operation' + args: + - management + - start + _management_stop: + type: string + metadata: + vintner_ignore: 'true' + default: + eval: + python: '{{ "project" | get_dir }}/vintner_utils.py#get_operation' + args: + - management + - stop + _management_delete: + type: string + metadata: + vintner_ignore: 'true' + default: + eval: + python: '{{ "project" | get_dir }}/vintner_utils.py#get_operation' + args: + - management + - delete + requirements: + - host: + capability: tosca.capabilities.Compute + relationship: tosca.relationships.HostedOn + interfaces: + management: + type: management + service.application: + derived_from: software.application + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + application_language: + type: string + application_port: + type: string + metadata: + vintner_name: PORT + application_protocol: + type: string + attributes: + application_address: + type: string + application_endpoint: + type: string + default: + concat: + - eval: .::application_protocol + - '://' + - eval: .::application_address + - ':' + - eval: .::application_port + software.runtime: + derived_from: software.application + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + capabilities: + host: + type: tosca.capabilities.Compute + container.runtime: + derived_from: software.runtime + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + machine: + derived_from: node + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + machine_name: + type: string + local.machine: + derived_from: machine + metadata: + vintner_normative: 'true' + capabilities: + host: + type: tosca.capabilities.Compute + remote.machine: + derived_from: machine + metadata: + vintner_normative: 'true' + properties: + machine_name: + type: string + ports: + type: list + entry_schema: + type: string + flavor: + type: string + default: m1.medium + network: + type: string + ssh_user: + type: string + ssh_key_name: + type: string + ssh_key_file: + type: string + attributes: + management_address: + type: string + application_address: + type: string + default: + eval: .::management_address + capabilities: + host: + type: tosca.capabilities.Compute + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + virtual.machine: + derived_from: remote.machine + physical.machine: + derived_from: remote.machine + database: + derived_from: node + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + requirements: + - host: + capability: tosca.capabilities.Compute + relationship: tosca.relationships.HostedOn + relational.database: + derived_from: database + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + dbms: + derived_from: software.application + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + relational.dbms: + derived_from: dbms + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + storage: + derived_from: node + block.storage: + derived_from: storage + object.storage: + derived_from: storage + file.storage: + derived_from: storage + bucket: + derived_from: object.storage + metadata: + vintner_normative: 'true' + properties: + bucket_name: + type: string + bucket_dialect: + type: string + attributes: + bucket_endpoint: + type: string + bucket_token: + type: string + requirements: + - host: + capability: tosca.capabilities.Compute + relationship: tosca.relationships.HostedOn + ingress: + derived_from: node + metadata: + vintner_normative: 'true' + properties: + application_name: + type: string + default: + eval: .::.requirements::[.name=application]::.target::application_name + application_port: + type: string + default: + eval: .::.requirements::[.name=application]::.target::application_port + application_protocol: + type: string + default: + eval: .::.requirements::[.name=application]::.target::application_protocol + attributes: + application_address: + type: string + requirements: + - application: + capability: tosca.capabilities.Endpoint + relationship: tosca.relationships.ConnectsTo + - host: + capability: tosca.capabilities.Compute + relationship: tosca.relationships.HostedOn diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml new file mode 100644 index 0000000000..06693333a1 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml @@ -0,0 +1,470 @@ +################################################### +# +# WARNING: Do not edit! This file is autogenerated! +# +################################################### + +tosca_definitions_version: tosca_simple_yaml_1_3 +description: TOSCA Profile for OpenTOSCA Vintner (Extended) +metadata: + vintner_normative: 'true' + template_name: TOSCA Vintner Profile (Extended) + template_author: Miles Stötzner + template_contact: miles.stoetzner@iste.uni-stuttgart.de + template_link: https://vintner.opentosca.org + template_version: 1.0.0-draft + template_id: tosca-vintner-profile + template_license: https://www.apache.org/licenses/LICENSE-2.0 + acknowledgments: Partially funded by the [German Federal Ministry for Economic Affairs and Climate Action (BMWK)](https://www.bmwk.de) as part of the research project [SofDCar (19S21002)](https://sofdcar.de). + vintner_orchestrator: unfurl +imports: + - tosca-vintner-profile-core.yaml +artifact_types: + docker.image: + derived_from: container.image + description: expects image reference in "file" + zip.archive: + derived_from: source.archive + tar.archive: + derived_from: source.archive + apt.package: + derived_from: system.package + properties: + script: + type: string + required: false + description: URL of an installation script + repository: + type: string + required: false + description: name of the repository (required if source is set) + key: + type: string + required: false + description: URL of the apt key which signs the apt repository (required if source is set) + source: + type: string + required: false + description: source of the repository + dependencies: + type: string + required: false + description: Comma separated list of apt packages that are additionally installed + env: + type: string + required: false + description: Space separated env variables + default: '' +node_types: + nodejs.runtime: + derived_from: software.runtime + metadata: + vintner_normative: 'true' + properties: + application_name: + type: string + default: nodejs + artifacts: + apt_package: + type: apt.package + file: nodejs + properties: + script: https://deb.nodesource.com/setup_18.x + attributes: + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + capabilities: + host: + type: tosca.capabilities.Compute + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + nodejs.service.application: + derived_from: service.application + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + application_language: + type: string + default: nodejs18 + interfaces: + management: + type: management + operations: + configure: npm ci + start: npm start + python.runtime: + derived_from: software.runtime + metadata: + vintner_normative: 'true' + artifacts: + apt_package: + type: apt.package + file: python-is-python3 + properties: + dependencies: + type: string + default: python3 python3-pip python3-venv + attributes: + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + capabilities: + host: + type: tosca.capabilities.Compute + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + python.service.application: + derived_from: service.application + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + application_language: + type: string + default: python3 + interfaces: + management: + type: management + operations: + configure: pip install -r requirements.txt + start: python main.py + go.service.application: + derived_from: service.application + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + application_language: + type: string + default: go122 + java.runtime: + derived_from: software.runtime + metadata: + vintner_normative: 'true' + properties: + application_name: + type: string + default: java + artifacts: + apt_package: + type: apt.package + file: openjdk-18-jre-headless + attributes: + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + capabilities: + host: + type: tosca.capabilities.Compute + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + java.service.application: + derived_from: service.application + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + application_language: + type: string + default: java21 + dotnet.runtime: + derived_from: software.runtime + metadata: + vintner_normative: 'true' + properties: + application_name: + type: string + default: java + artifacts: + apt_package: + type: apt.package + file: dotnet-sdk-8.0 + attributes: + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + capabilities: + host: + type: tosca.capabilities.Compute + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + csharp.service.application: + derived_from: service.application + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + application_language: + type: string + default: dotnet8 + binary.service.application: + derived_from: service.application + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + application_language: + type: string + default: binary + interfaces: + management: + type: management + operations: + start: ./{{ SELF.application_name }} + gcp.provider: + derived_from: cloud.provider + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + _hosting: + type: string + default: gcp + gcp_region: + type: string + gcp_service_account_file: + type: string + gcp_project: + type: string + interfaces: + Standard: + operations: + create: exit 0 + delete: exit 0 + gcp.service: + derived_from: cloud.service + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + _hosting: + type: string + default: gcp + gcp_service: + type: string + default: must-be-overridden + gcp.cloudrun: + derived_from: gcp.service + metadata: + vintner_normative: 'true' + properties: + gcp_service: + type: string + default: run.googleapis.com + gcp.cloudsql: + derived_from: gcp.service + metadata: + vintner_normative: 'true' + properties: + gcp_service: + type: string + default: sqladmin.googleapis.com + gcp.appengine: + derived_from: gcp.service + metadata: + vintner_normative: 'true' + properties: + gcp_service: + type: string + default: appengine.googleapis.com + requirements: + - build: + capability: tosca.capabilities.Root + relationship: tosca.relationships.DependsOn + - reporting: + capability: tosca.capabilities.Root + relationship: tosca.relationships.DependsOn + gcp.appenginereporting: + derived_from: gcp.service + metadata: + vintner_normative: 'true' + properties: + gcp_service: + type: string + default: appenginereporting.googleapis.com + gcp.cloudbuild: + derived_from: gcp.service + metadata: + vintner_normative: 'true' + properties: + gcp_service: + type: string + default: cloudbuild.googleapis.com + gcp.kubernetesengine: + derived_from: gcp.service + metadata: + vintner_normative: 'true' + properties: + gcp_service: + type: string + default: container.googleapis.com + gcp.cloudstorage: + derived_from: gcp.service + metadata: + vintner_normative: 'true' + properties: + gcp_service: + type: string + default: storage.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: + application_name: + type: string + default: docker + _hosting: + type: string + default: docker + attributes: + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + capabilities: + host: + type: tosca.capabilities.Compute + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + kubernetes.cluster: + derived_from: cloud.service + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + _hosting: + type: string + default: kubernetes + k8s_host: + type: string + k8s_ca_cert_file: + type: string + k8s_client_cert_file: + type: string + k8s_client_key_file: + type: string + capabilities: + host: + type: tosca.capabilities.Compute + interfaces: + Standard: + operations: + create: exit 0 + delete: exit 0 + openstack.provider: + derived_from: cloud.provider + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + _hosting: + type: string + default: openstack + os_region_name: + type: string + os_auth_type: + type: string + os_auth_url: + type: string + os_identity_api_version: + type: string + os_interface: + type: string + os_application_credential_id: + type: string + os_application_credential_secret: + type: string + interfaces: + Standard: + operations: + create: exit 0 + delete: exit 0 + mysql.dbms: + derived_from: relational.dbms + metadata: + vintner_normative: 'true' + properties: + dbms_name: + type: string + application_name: + type: string + default: + eval: .::dbms_name + dbms_password: + type: string + dbms_ssl_mode: + type: string + default: None + attributes: + application_address: + type: string + application_port: + type: string + management_address: + type: string + management_port: + type: string + capabilities: + host: + type: tosca.capabilities.Compute + requirements: + - host: + capability: tosca.capabilities.Compute + relationship: tosca.relationships.HostedOn + mysql.database: + derived_from: relational.database + metadata: + vintner_normative: 'true' + properties: + database_name: + type: string + database_user: + type: string + database_password: + type: string + attributes: + application_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::application_address + application_port: + type: string + default: + eval: .::.requirements::[.name=host]::.target::application_port + capabilities: + database: + type: tosca.capabilities.Endpoint.Database + requirements: + - host: + capability: tosca.capabilities.Compute + relationship: tosca.relationships.HostedOn + minio.server: + derived_from: software.application diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile.yaml new file mode 100644 index 0000000000..8c2c83560a --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile.yaml @@ -0,0 +1,21 @@ +################################################### +# +# WARNING: Do not edit! This file is autogenerated! +# +################################################### + +tosca_definitions_version: tosca_simple_yaml_1_3 +description: TOSCA Profile for OpenTOSCA Vintner +metadata: + vintner_normative: 'true' + template_name: TOSCA Vintner Profile + template_author: Miles Stötzner + template_contact: miles.stoetzner@iste.uni-stuttgart.de + template_link: https://vintner.opentosca.org + template_version: 1.0.0-draft + template_id: tosca-vintner-profile + template_license: https://www.apache.org/licenses/LICENSE-2.0 + acknowledgments: Partially funded by the [German Federal Ministry for Economic Affairs and Climate Action (BMWK)](https://www.bmwk.de) as part of the research project [SofDCar (19S21002)](https://sofdcar.de). +imports: + - ./tosca-vintner-profile-core.yaml + - ./tosca-vintner-profile-extended.yaml diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/types.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/types.yaml new file mode 100644 index 0000000000..ee9b69ba7c --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/types.yaml @@ -0,0 +1,4 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 +imports: + - tosca-vintner-profile.yaml + - retailer.yaml diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/clean.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/clean.sh new file mode 100755 index 0000000000..dc174b7f71 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/clean.sh @@ -0,0 +1,11 @@ +#! /usr/bin/bash +set -e + +# Set working directory +cd "$(dirname "$0")" + +# Load configuration +source configuration.sh + +# Clean +$VINTNER setup clean --force diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/code.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/code.sh new file mode 100755 index 0000000000..dbe3358fb5 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/code.sh @@ -0,0 +1,11 @@ +#! /usr/bin/bash +set -e + +# Set working directory +cd "$(dirname "$0")" + +# Load configuration +source configuration.sh + +# Open VS Code +$VINTNER instances code --instance ${TEMPLATE_NAME} \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.env b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.env new file mode 100644 index 0000000000..0764bfb3f1 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.env @@ -0,0 +1,5 @@ +TEMPLATE_NAME="technology-gcp" +#VINTNER="node ../../../build/cli/index.js" +VINTNER="../../../task vintner" +ORCHESTRATOR="unfurl" +VARIANT="os-medium" diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.sh new file mode 100755 index 0000000000..9c517b8682 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.sh @@ -0,0 +1,36 @@ +#! /usr/bin/bash +set -e + +# Set working directory +cd "$(dirname "$0")" + +# Load configuration +source configuration.env + +# Check that TEMPLATE_NAME is defined +if [[ -z ${TEMPLATE_NAME} ]]; then + echo "TEMPLATE_NAME is not defined" + exit 1 +fi + +# Check that VINTNER is defined +if [[ -z ${VINTNER} ]]; then + echo "VINTNER is not defined" + exit 1 +fi + + +# Check that VARIANT is defined +if [[ -z ${VARIANT} ]]; then + echo "VARIANT is not defined" + exit 1 +fi + +# Check that ORCHESTRATOR is defined +if [[ -z ${ORCHESTRATOR} ]]; then + echo "ORCHESTRATOR is not defined" + exit 1 +fi + +# Set template directory +TEMPLATE_DIR=$(readlink -f $(dirname $0)/../) diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/continue.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/continue.sh new file mode 100755 index 0000000000..4784e34fb6 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/continue.sh @@ -0,0 +1,11 @@ +#! /usr/bin/bash +set -e + +# Set working directory +cd "$(dirname "$0")" + +# Load configuration +source configuration.sh + +# Continue deployment +$VINTNER instances continue --instance ${TEMPLATE_NAME} --force diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/deploy.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/deploy.sh new file mode 100755 index 0000000000..00aaf273b2 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/deploy.sh @@ -0,0 +1,16 @@ +#! /usr/bin/bash +set -e + +# Set working directory +cd "$(dirname "$0")" + +# Load configuration +source configuration.sh + +$VINTNER template pull --dir ${TEMPLATE_DIR} +$VINTNER template implement --dir ${TEMPLATE_DIR} --experimental +$VINTNER templates import --template ${TEMPLATE_NAME} --path ${TEMPLATE_DIR} +$VINTNER instances init --instance ${TEMPLATE_NAME} --template ${TEMPLATE_NAME} +$VINTNER instances resolve --instance ${TEMPLATE_NAME} --inputs ${TEMPLATE_DIR}/tests/${VARIANT}/inputs.yaml +$VINTNER instances validate --instance ${TEMPLATE_NAME} --inputs ${TEMPLATE_DIR}/deployment-inputs.ignored.yaml +$VINTNER instances deploy --instance ${TEMPLATE_NAME} --inputs ${TEMPLATE_DIR}/deployment-inputs.ignored.yaml diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/enrich.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/enrich.sh new file mode 100755 index 0000000000..8e2ca88227 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/enrich.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +# Load configuration +source configuration.sh + +# Enrich +$VINTNER template enrich --template ${TEMPLATE_DIR}/variable-service-template.yaml --output ${TEMPLATE_DIR}/enriched.yaml diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/implement.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/implement.sh new file mode 100755 index 0000000000..0ac779ce2c --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/implement.sh @@ -0,0 +1,8 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +# Implement types +$VINTNER template implement --dir ${TEMPLATE_DIR} --experimental diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/pull.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/pull.sh new file mode 100755 index 0000000000..90f0358264 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/pull.sh @@ -0,0 +1,9 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +# Pull dependencies +$VINTNER template pull --dir ${TEMPLATE_DIR} + diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh new file mode 100755 index 0000000000..640d86d97d --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh @@ -0,0 +1,13 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +# Quality +#for dir in ../tests/*/; +for dir in "../tests/gcp"; +do + dir=$(basename $dir) + echo "${dir}: $($VINTNER template quality --template ${TEMPLATE_DIR}/variable-service-template.yaml --experimental --inputs ${TEMPLATE_DIR}/tests/${dir}/inputs.yaml)" +done diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/reimport.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/reimport.sh new file mode 100755 index 0000000000..5a7316f121 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/reimport.sh @@ -0,0 +1,20 @@ +#! /usr/bin/bash +set -e + +# Set working directory +cd "$(dirname "$0")" + +# Load configuration +source configuration.sh + +$VINTNER instances undeploy --instance ${TEMPLATE_NAME} || true + +$VINTNER instances delete --instance ${TEMPLATE_NAME} --force || true +$VINTNER templates delete --template ${TEMPLATE_NAME} || true + +$VINTNER template pull --dir ${TEMPLATE_DIR} +$VINTNER templates import --template ${TEMPLATE_NAME} --path ${TEMPLATE_DIR} +$VINTNER instances init --instance ${TEMPLATE_NAME} --template ${TEMPLATE_NAME} +$VINTNER instances resolve --instance ${TEMPLATE_NAME} --inputs ${TEMPLATE_DIR}/tests/${VARIANT}/inputs.yaml +$VINTNER instances validate --instance ${TEMPLATE_NAME} --inputs ${TEMPLATE_DIR}/deployment-inputs.ignored.yaml +$VINTNER instances deploy --instance ${TEMPLATE_NAME} --inputs ${TEMPLATE_DIR}/deployment-inputs.ignored.yaml diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/setup.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/setup.sh new file mode 100755 index 0000000000..519cac182c --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/setup.sh @@ -0,0 +1,14 @@ +#! /usr/bin/bash +set -e + +# Set working directory +cd "$(dirname "$0")" + +# Load configuration +source configuration.sh + +# Setup +$VINTNER setup init +$VINTNER orchestrators init ${ORCHESTRATOR} +$VINTNER orchestrators enable --orchestrator ${ORCHESTRATOR} +$VINTNER orchestrators attest --orchestrator ${ORCHESTRATOR} \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-001.txt b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-001.txt new file mode 100644 index 0000000000..8fdd476737 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-001.txt @@ -0,0 +1,107 @@ + +The technology rules of our case study. Qualities range from bad (0) to good (1). +┌─────────┬──────────────┬────────────────────────┬─────────────────────────────────────────────┬─────────┐ +│ (index) │ Technology │ Component │ Hosting │ Quality │ +├─────────┼──────────────┼────────────────────────┼─────────────────────────────────────────────┼─────────┤ +│ 0 │ 'ansible' │ 'software.application' │ [ 'software.runtime', 'openstack.machine' ] │ 1 │ +│ 1 │ 'ansible' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ +│ 2 │ 'ansible' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ +│ 3 │ 'ansible' │ 'software.application' │ [ 'gcp.appengine' ] │ 0 │ +│ 4 │ 'ansible' │ 'software.runtime' │ [ 'openstack.machine' ] │ 1 │ +│ 5 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ +│ 6 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ +│ 7 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ +│ 8 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ +│ 9 │ 'ansible' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 1 │ +│ 10 │ 'ansible' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ +│ 11 │ 'ansible' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ +│ 12 │ 'ansible' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ +│ 13 │ 'ansible' │ 'ingress' │ [ 'openstack.machine' ] │ 1 │ +│ 14 │ 'ansible' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ +│ 15 │ 'ansible' │ 'openstack.machine' │ undefined │ 0.5 │ +│ 16 │ 'ansible' │ 'gcp.service' │ undefined │ 1 │ +│ 17 │ 'terraform' │ 'software.application' │ [ 'software.runtime', 'openstack.machine' ] │ 0 │ +│ 18 │ 'terraform' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ +│ 19 │ 'terraform' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ +│ 20 │ 'terraform' │ 'software.application' │ [ 'gcp.appengine' ] │ 1 │ +│ 21 │ 'terraform' │ 'software.runtime' │ [ 'openstack.machine' ] │ 0 │ +│ 22 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ +│ 23 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ +│ 24 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ +│ 25 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ +│ 26 │ 'terraform' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 0 │ +│ 27 │ 'terraform' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ +│ 28 │ 'terraform' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ +│ 29 │ 'terraform' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ +│ 30 │ 'terraform' │ 'ingress' │ [ 'openstack.machine' ] │ 0 │ +│ 31 │ 'terraform' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ +│ 32 │ 'terraform' │ 'openstack.machine' │ undefined │ 1 │ +│ 33 │ 'terraform' │ 'gcp.service' │ undefined │ 1 │ +│ 34 │ 'kubernetes' │ 'software.application' │ [ 'kubernetes' ] │ 1 │ +│ 35 │ 'kubernetes' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 0 │ +│ 36 │ 'kubernetes' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 1 │ +│ 37 │ 'kubernetes' │ 'ingress' │ [ 'kubernetes' ] │ 1 │ +│ 38 │ 'docker' │ 'software.application' │ [ 'docker.engine' ] │ 1 │ +│ 39 │ 'docker' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 0 │ +│ 40 │ 'docker' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 1 │ +└─────────┴──────────────┴────────────────────────┴─────────────────────────────────────────────┴─────────┘ + +Metrics relevant when modeling the different scenarios +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────┐ +│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────┤ +│ 0 │ 'EDMM Docker Variant' │ 1 │ 49 │ 0 │ 12 │ 187 │ │ +│ 1 │ 'EDMM GCP Variant' │ 1 │ 57 │ 0 │ 12 │ 204 │ │ +│ 2 │ 'EDMM OS Large Variant' │ 1 │ 93 │ 0 │ 18 │ 284 │ │ +│ 3 │ 'EDMM OS Medium Variant' │ 1 │ 93 │ 0 │ 18 │ 284 │ │ +│ 4 │ 'EDMM Total (EDMM Docker Variant, EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant)' │ 4 │ 292 │ 0 │ 60 │ 959 │ 'EDMM Total' │ +│ 5 │ 'VDMM Baseline Default' │ 1 │ 192 │ 10 │ 44 │ 557 │ │ +│ 6 │ 'VDMM+ Default Manual' │ 1 │ 130 │ 42 │ 45 │ 461 │ │ +│ 7 │ 'VDMM+ Default Automated Random' │ 1 │ 130 │ 5 │ 0 │ 371 │ │ +│ 8 │ 'VDMM+ Default Automated Counting' │ 1 │ 130 │ 5 │ 0 │ 372 │ │ +│ 9 │ 'VDMM+ Default Automated Quality' │ 1 │ 130 │ 5 │ 0 │ 368 │ │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────┘ + +Qualities of the derived deployment models, i.e., the deployment variants, of the different scenarios ranging from bad (0) to good (1). +┌─────────┬──────────────┬────────┬─────────────┬─────────────┬────────────────┬─────────┐ +│ (index) │ scenario │ expert │ non_expert │ random │ counting │ quality │ +├─────────┼──────────────┼────────┼─────────────┼─────────────┼────────────────┼─────────┤ +│ 0 │ 'docker' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.92 ] │ 1 │ +│ 1 │ 'gcp' │ 1 │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ 1 │ +│ 2 │ 'kubernetes' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.92 ] │ 1 │ +│ 3 │ 'os-large' │ 1 │ [ 0.08, 1 ] │ [ 0.08, 1 ] │ [ 0.11, 0.97 ] │ 1 │ +│ 4 │ 'os-medium' │ 1 │ [ 0.08, 1 ] │ [ 0.08, 1 ] │ [ 0.11, 0.97 ] │ 1 │ +└─────────┴──────────────┴────────┴─────────────┴─────────────┴────────────────┴─────────┘ + +Metrics relevant when modeling the maintenance scenario of our case study +┌─────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────────────────┐ +│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ +├─────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────────────────┤ +│ 0 │ 'EDMM Kubernetes' │ 1 │ 60 │ 0 │ 12 │ 209 │ │ +│ 1 │ 'EDMM Total Maintenance (EDMM Docker Variant, EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant, EDMM Kubernetes)' │ 5 │ 352 │ 0 │ 72 │ 1168 │ 'EDMM Total Maintenance' │ +│ 2 │ 'VDMM Baseline Maintenance' │ 1 │ 262 │ 29 │ 56 │ 752 │ │ +│ 3 │ 'VDMM+ Maintenance Manual' │ 1 │ 157 │ 60 │ 58 │ 554 │ │ +│ 4 │ 'VDMM+ Maintenance Automated Random' │ 1 │ 157 │ 10 │ 0 │ 437 │ │ +│ 5 │ 'VDMM+ Maintenance Automated Counting' │ 1 │ 157 │ 10 │ 0 │ 438 │ │ +│ 6 │ 'VDMM+ Maintenance Automated Quality' │ 1 │ 157 │ 10 │ 0 │ 434 │ │ +└─────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────────────────┘ + +From Default to Maintained (Absolut to previous) +┌─────────┬─────────────────────────────────────────────────────────────────────────┬──────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ +│ (index) │ scenario │ models_absolute_diff │ elements_absolute_diff │ conditions_absolute_diff │ technology_assignments_absolute_diff │ lines_of_code_absolute_diff │ +├─────────┼─────────────────────────────────────────────────────────────────────────┼──────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ +│ 0 │ 'EDMM Total Maintenance - EDMM Total' │ 1 │ 60 │ 0 │ 12 │ 209 │ +│ 1 │ 'VDMM Baseline Maintenance - VDMM Baseline Default' │ 0 │ 70 │ 19 │ 12 │ 195 │ +│ 2 │ 'VDMM+ Maintenance Manual - VDMM+ Default Manual' │ 0 │ 27 │ 18 │ 13 │ 93 │ +│ 3 │ 'VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality' │ 0 │ 27 │ 5 │ 0 │ 66 │ +└─────────┴─────────────────────────────────────────────────────────────────────────┴──────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ + +From Default to Maintained (Relative to change to baseline) +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ +│ (index) │ scenario │ elements_relative_diff │ conditions_relative_diff │ technology_assignments_relative_diff │ lines_of_code_relative_diff │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ +│ 0 │ '(VDMM+ Maintenance Manual - VDMM+ Default Manual) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.39 │ 0.95 │ 1.08 │ 0.48 │ +│ 1 │ '(VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.39 │ 0.26 │ 0 │ 0.34 │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ + +> Original \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-002.txt b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-002.txt new file mode 100644 index 0000000000..70464a2d8a --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-002.txt @@ -0,0 +1,106 @@ + +The technology rules of our case study. Qualities range from bad (0) to good (1). +┌─────────┬──────────────┬────────────────────────┬─────────────────────────────────────────────┬─────────┐ +│ (index) │ Technology │ Component │ Hosting │ Quality │ +├─────────┼──────────────┼────────────────────────┼─────────────────────────────────────────────┼─────────┤ +│ 0 │ 'ansible' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ +│ 1 │ 'ansible' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ +│ 2 │ 'ansible' │ 'software.application' │ [ 'gcp.appengine' ] │ 0 │ +│ 3 │ 'ansible' │ 'software.application' │ [ 'openstack.machine' ] │ 1 │ +│ 4 │ 'ansible' │ 'docker.engine' │ [ 'openstack.machine' ] │ 1 │ +│ 5 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ +│ 6 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ +│ 7 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ +│ 8 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ +│ 9 │ 'ansible' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 1 │ +│ 10 │ 'ansible' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ +│ 11 │ 'ansible' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ +│ 12 │ 'ansible' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ +│ 13 │ 'ansible' │ 'ingress' │ [ 'openstack.machine' ] │ 1 │ +│ 14 │ 'ansible' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ +│ 15 │ 'ansible' │ 'openstack.machine' │ undefined │ 0.5 │ +│ 16 │ 'ansible' │ 'gcp.service' │ undefined │ 1 │ +│ 17 │ 'terraform' │ 'software.application' │ [ 'software.runtime', 'openstack.machine' ] │ 0 │ +│ 18 │ 'terraform' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ +│ 19 │ 'terraform' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ +│ 20 │ 'terraform' │ 'software.application' │ [ 'gcp.appengine' ] │ 1 │ +│ 21 │ 'terraform' │ 'software.application' │ [ 'openstack.machine' ] │ 0 │ +│ 22 │ 'terraform' │ 'docker.engine' │ [ 'openstack.machine' ] │ 0 │ +│ 23 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ +│ 24 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ +│ 25 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ +│ 26 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ +│ 27 │ 'terraform' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 0 │ +│ 28 │ 'terraform' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ +│ 29 │ 'terraform' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ +│ 30 │ 'terraform' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ +│ 31 │ 'terraform' │ 'ingress' │ [ 'openstack.machine' ] │ 0 │ +│ 32 │ 'terraform' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ +│ 33 │ 'terraform' │ 'openstack.machine' │ undefined │ 1 │ +│ 34 │ 'terraform' │ 'gcp.service' │ undefined │ 1 │ +│ 35 │ 'kubernetes' │ 'software.application' │ [ 'kubernetes' ] │ 1 │ +│ 36 │ 'kubernetes' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 0 │ +│ 37 │ 'kubernetes' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 1 │ +│ 38 │ 'kubernetes' │ 'ingress' │ [ 'kubernetes' ] │ 1 │ +│ 39 │ 'docker' │ 'software.application' │ [ 'docker.engine' ] │ 1 │ +│ 40 │ 'docker' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 0 │ +│ 41 │ 'docker' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 1 │ +└─────────┴──────────────┴────────────────────────┴─────────────────────────────────────────────┴─────────┘ + +Metrics relevant when modeling the different scenarios +┌─────────┬────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────┐ +│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ +├─────────┼────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────┤ +│ 0 │ 'EDMM GCP Variant' │ 1 │ 57 │ 0 │ 14 │ 206 │ │ +│ 1 │ 'EDMM OS Large Variant' │ 1 │ 86 │ 0 │ 18 │ 269 │ │ +│ 2 │ 'EDMM OS Medium Variant' │ 1 │ 86 │ 0 │ 18 │ 269 │ │ +│ 3 │ 'EDMM Total (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant)' │ 3 │ 229 │ 0 │ 50 │ 744 │ 'EDMM Total' │ +│ 4 │ 'VDMM Baseline Default' │ 1 │ 138 │ 8 │ 31 │ 424 │ │ +│ 5 │ 'VDMM+ Default Manual' │ 1 │ 109 │ 27 │ 31 │ 389 │ │ +│ 6 │ 'VDMM+ Default Automated Random' │ 1 │ 109 │ 4 │ 0 │ 326 │ │ +│ 7 │ 'VDMM+ Default Automated Counting' │ 1 │ 109 │ 4 │ 0 │ 327 │ │ +│ 8 │ 'VDMM+ Default Automated Quality' │ 1 │ 109 │ 4 │ 0 │ 323 │ │ +└─────────┴────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────┘ + +Qualities of the derived deployment models, i.e., the deployment variants, of the different scenarios ranging from bad (0) to good (1). +┌─────────┬──────────────┬────────┬─────────────┬─────────────┬────────────────┬─────────┐ +│ (index) │ scenario │ expert │ non_expert │ random │ counting │ quality │ +├─────────┼──────────────┼────────┼─────────────┼─────────────┼────────────────┼─────────┤ +│ 0 │ 'gcp' │ 1 │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ 1 │ +│ 1 │ 'kubernetes' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.92 ] │ 1 │ +│ 2 │ 'os-large' │ 1 │ [ 0.33, 1 ] │ [ 0.33, 1 ] │ [ 0.42, 0.67 ] │ 1 │ +│ 3 │ 'os-medium' │ 1 │ [ 0.33, 1 ] │ [ 0.33, 1 ] │ [ 0.42, 0.67 ] │ 1 │ +└─────────┴──────────────┴────────┴─────────────┴─────────────┴────────────────┴─────────┘ + +Metrics relevant when modeling the maintenance scenario of our case study +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────────────────┐ +│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────────────────┤ +│ 0 │ 'EDMM Kubernetes' │ 1 │ 60 │ 0 │ 13 │ 210 │ │ +│ 1 │ 'EDMM Total Maintenance (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant, EDMM Kubernetes)' │ 4 │ 289 │ 0 │ 63 │ 954 │ 'EDMM Total Maintenance' │ +│ 2 │ 'VDMM Baseline Maintenance' │ 1 │ 204 │ 23 │ 43 │ 606 │ │ +│ 3 │ 'VDMM+ Maintenance Manual' │ 1 │ 136 │ 44 │ 43 │ 479 │ │ +│ 4 │ 'VDMM+ Maintenance Automated Random' │ 1 │ 136 │ 9 │ 0 │ 394 │ │ +│ 5 │ 'VDMM+ Maintenance Automated Counting' │ 1 │ 136 │ 9 │ 0 │ 395 │ │ +│ 6 │ 'VDMM+ Maintenance Automated Quality' │ 1 │ 136 │ 9 │ 0 │ 391 │ │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────────────────┘ + +From Default to Maintained (Absolut to previous) +┌─────────┬─────────────────────────────────────────────────────────────────────────┬──────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ +│ (index) │ scenario │ models_absolute_diff │ elements_absolute_diff │ conditions_absolute_diff │ technology_assignments_absolute_diff │ lines_of_code_absolute_diff │ +├─────────┼─────────────────────────────────────────────────────────────────────────┼──────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ +│ 0 │ 'EDMM Total Maintenance - EDMM Total' │ 1 │ 60 │ 0 │ 13 │ 210 │ +│ 1 │ 'VDMM Baseline Maintenance - VDMM Baseline Default' │ 0 │ 66 │ 15 │ 12 │ 182 │ +│ 2 │ 'VDMM+ Maintenance Manual - VDMM+ Default Manual' │ 0 │ 27 │ 17 │ 12 │ 90 │ +│ 3 │ 'VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality' │ 0 │ 27 │ 5 │ 0 │ 68 │ +└─────────┴─────────────────────────────────────────────────────────────────────────┴──────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ + +From Default to Maintained (Relative to change to baseline) +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ +│ (index) │ scenario │ elements_relative_diff │ conditions_relative_diff │ technology_assignments_relative_diff │ lines_of_code_relative_diff │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ +│ 0 │ '(VDMM+ Maintenance Manual - VDMM+ Default Manual) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.41 │ 1.13 │ 1 │ 0.49 │ +│ 1 │ '(VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.41 │ 0.33 │ 0 │ 0.37 │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ + +> Diff: Docker on VM \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-003.txt b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-003.txt new file mode 100644 index 0000000000..09a831f22a --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-003.txt @@ -0,0 +1,106 @@ + +The technology rules of our case study. Qualities range from bad (0) to good (1). +┌─────────┬──────────────┬────────────────────────┬─────────────────────────────────────────────┬─────────┐ +│ (index) │ Technology │ Component │ Hosting │ Quality │ +├─────────┼──────────────┼────────────────────────┼─────────────────────────────────────────────┼─────────┤ +│ 0 │ 'ansible' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ +│ 1 │ 'ansible' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ +│ 2 │ 'ansible' │ 'software.application' │ [ 'gcp.appengine' ] │ 0 │ +│ 3 │ 'ansible' │ 'software.application' │ [ 'openstack.machine' ] │ 1 │ +│ 4 │ 'ansible' │ 'docker.engine' │ [ 'openstack.machine' ] │ 1 │ +│ 5 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ +│ 6 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ +│ 7 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ +│ 8 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ +│ 9 │ 'ansible' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 1 │ +│ 10 │ 'ansible' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ +│ 11 │ 'ansible' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ +│ 12 │ 'ansible' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ +│ 13 │ 'ansible' │ 'ingress' │ [ 'openstack.machine' ] │ 1 │ +│ 14 │ 'ansible' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ +│ 15 │ 'ansible' │ 'openstack.machine' │ undefined │ 0.5 │ +│ 16 │ 'ansible' │ 'gcp.service' │ undefined │ 1 │ +│ 17 │ 'terraform' │ 'software.application' │ [ 'software.runtime', 'openstack.machine' ] │ 0 │ +│ 18 │ 'terraform' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ +│ 19 │ 'terraform' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ +│ 20 │ 'terraform' │ 'software.application' │ [ 'gcp.appengine' ] │ 1 │ +│ 21 │ 'terraform' │ 'software.application' │ [ 'openstack.machine' ] │ 0 │ +│ 22 │ 'terraform' │ 'docker.engine' │ [ 'openstack.machine' ] │ 0 │ +│ 23 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ +│ 24 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ +│ 25 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ +│ 26 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ +│ 27 │ 'terraform' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 0 │ +│ 28 │ 'terraform' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ +│ 29 │ 'terraform' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ +│ 30 │ 'terraform' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ +│ 31 │ 'terraform' │ 'ingress' │ [ 'openstack.machine' ] │ 0 │ +│ 32 │ 'terraform' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ +│ 33 │ 'terraform' │ 'openstack.machine' │ undefined │ 1 │ +│ 34 │ 'terraform' │ 'gcp.service' │ undefined │ 1 │ +│ 35 │ 'kubernetes' │ 'software.application' │ [ 'kubernetes' ] │ 1 │ +│ 36 │ 'kubernetes' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 0 │ +│ 37 │ 'kubernetes' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 1 │ +│ 38 │ 'kubernetes' │ 'ingress' │ [ 'kubernetes' ] │ 1 │ +│ 39 │ 'docker' │ 'software.application' │ [ 'docker.engine' ] │ 1 │ +│ 40 │ 'docker' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 0 │ +│ 41 │ 'docker' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 1 │ +└─────────┴──────────────┴────────────────────────┴─────────────────────────────────────────────┴─────────┘ + +Metrics relevant when modeling the different scenarios +┌─────────┬────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────┐ +│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ +├─────────┼────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────┤ +│ 0 │ 'EDMM GCP Variant' │ 1 │ 74 │ 0 │ 14 │ 227 │ │ +│ 1 │ 'EDMM OS Large Variant' │ 1 │ 104 │ 0 │ 18 │ 292 │ │ +│ 2 │ 'EDMM OS Medium Variant' │ 1 │ 104 │ 0 │ 18 │ 292 │ │ +│ 3 │ 'EDMM Total (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant)' │ 3 │ 282 │ 0 │ 50 │ 811 │ 'EDMM Total' │ +│ 4 │ 'VDMM Baseline Default' │ 1 │ 173 │ 8 │ 31 │ 468 │ │ +│ 5 │ 'VDMM+ Default Manual' │ 1 │ 127 │ 27 │ 31 │ 412 │ │ +│ 6 │ 'VDMM+ Default Automated Random' │ 1 │ 127 │ 4 │ 0 │ 350 │ │ +│ 7 │ 'VDMM+ Default Automated Counting' │ 1 │ 127 │ 4 │ 0 │ 351 │ │ +│ 8 │ 'VDMM+ Default Automated Quality' │ 1 │ 127 │ 4 │ 0 │ 347 │ │ +└─────────┴────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────┘ + +Qualities of the derived deployment models, i.e., the deployment variants, of the different scenarios ranging from bad (0) to good (1). +┌─────────┬──────────────┬────────┬─────────────┬─────────────┬────────────────┬─────────┬──────────────────┐ +│ (index) │ scenario │ expert │ non_expert │ random │ counting │ quality │ quality_counting │ +├─────────┼──────────────┼────────┼─────────────┼─────────────┼────────────────┼─────────┼──────────────────┤ +│ 0 │ 'gcp' │ 1 │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ 1 │ 1 │ +│ 1 │ 'kubernetes' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.92 ] │ 1 │ 1 │ +│ 2 │ 'os-large' │ 1 │ [ 0.33, 1 ] │ [ 0.33, 1 ] │ [ 0.42, 0.67 ] │ 1 │ 1 │ +│ 3 │ 'os-medium' │ 1 │ [ 0.33, 1 ] │ [ 0.33, 1 ] │ [ 0.42, 0.67 ] │ 1 │ 1 │ +└─────────┴──────────────┴────────┴─────────────┴─────────────┴────────────────┴─────────┴──────────────────┘ + +Metrics relevant when modeling the maintenance scenario of our case study +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────────────────┐ +│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────────────────┤ +│ 0 │ 'EDMM Kubernetes' │ 1 │ 78 │ 0 │ 13 │ 233 │ │ +│ 1 │ 'EDMM Total Maintenance (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant, EDMM Kubernetes)' │ 4 │ 360 │ 0 │ 63 │ 1044 │ 'EDMM Total Maintenance' │ +│ 2 │ 'VDMM Baseline Maintenance' │ 1 │ 257 │ 23 │ 43 │ 673 │ │ +│ 3 │ 'VDMM+ Maintenance Manual' │ 1 │ 154 │ 44 │ 43 │ 502 │ │ +│ 4 │ 'VDMM+ Maintenance Automated Random' │ 1 │ 154 │ 9 │ 0 │ 418 │ │ +│ 5 │ 'VDMM+ Maintenance Automated Counting' │ 1 │ 154 │ 9 │ 0 │ 419 │ │ +│ 6 │ 'VDMM+ Maintenance Automated Quality' │ 1 │ 154 │ 9 │ 0 │ 415 │ │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────────────────┘ + +From Default to Maintained (Absolut to previous) +┌─────────┬─────────────────────────────────────────────────────────────────────────┬──────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ +│ (index) │ scenario │ models_absolute_diff │ elements_absolute_diff │ conditions_absolute_diff │ technology_assignments_absolute_diff │ lines_of_code_absolute_diff │ +├─────────┼─────────────────────────────────────────────────────────────────────────┼──────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ +│ 0 │ 'EDMM Total Maintenance - EDMM Total' │ 1 │ 78 │ 0 │ 13 │ 233 │ +│ 1 │ 'VDMM Baseline Maintenance - VDMM Baseline Default' │ 0 │ 84 │ 15 │ 12 │ 205 │ +│ 2 │ 'VDMM+ Maintenance Manual - VDMM+ Default Manual' │ 0 │ 27 │ 17 │ 12 │ 90 │ +│ 3 │ 'VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality' │ 0 │ 27 │ 5 │ 0 │ 68 │ +└─────────┴─────────────────────────────────────────────────────────────────────────┴──────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ + +From Default to Maintained (Relative to change to baseline) +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ +│ (index) │ scenario │ elements_relative_diff │ conditions_relative_diff │ technology_assignments_relative_diff │ lines_of_code_relative_diff │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ +│ 0 │ '(VDMM+ Maintenance Manual - VDMM+ Default Manual) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.32 │ 1.13 │ 1 │ 0.44 │ +│ 1 │ '(VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.32 │ 0.33 │ 0 │ 0.33 │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ + +> Diff: connection properties \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-004.txt b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-004.txt new file mode 100644 index 0000000000..9dff403f4d --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-004.txt @@ -0,0 +1,106 @@ + +The technology rules of our case study. Qualities range from bad (0) to good (1). +┌─────────┬──────────────┬────────────────────────┬─────────────────────────────────────────────┬─────────┐ +│ (index) │ Technology │ Component │ Hosting │ Quality │ +├─────────┼──────────────┼────────────────────────┼─────────────────────────────────────────────┼─────────┤ +│ 0 │ 'ansible' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ +│ 1 │ 'ansible' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ +│ 2 │ 'ansible' │ 'software.application' │ [ 'gcp.appengine' ] │ 0 │ +│ 3 │ 'ansible' │ 'software.application' │ [ 'openstack.machine' ] │ 1 │ +│ 4 │ 'ansible' │ 'docker.engine' │ [ 'openstack.machine' ] │ 1 │ +│ 5 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ +│ 6 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ +│ 7 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ +│ 8 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ +│ 9 │ 'ansible' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 1 │ +│ 10 │ 'ansible' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ +│ 11 │ 'ansible' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ +│ 12 │ 'ansible' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ +│ 13 │ 'ansible' │ 'ingress' │ [ 'openstack.machine' ] │ 1 │ +│ 14 │ 'ansible' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ +│ 15 │ 'ansible' │ 'openstack.machine' │ undefined │ 0.5 │ +│ 16 │ 'ansible' │ 'gcp.service' │ undefined │ 1 │ +│ 17 │ 'terraform' │ 'software.application' │ [ 'software.runtime', 'openstack.machine' ] │ 0 │ +│ 18 │ 'terraform' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ +│ 19 │ 'terraform' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ +│ 20 │ 'terraform' │ 'software.application' │ [ 'gcp.appengine' ] │ 1 │ +│ 21 │ 'terraform' │ 'software.application' │ [ 'openstack.machine' ] │ 0 │ +│ 22 │ 'terraform' │ 'docker.engine' │ [ 'openstack.machine' ] │ 0 │ +│ 23 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ +│ 24 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ +│ 25 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ +│ 26 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ +│ 27 │ 'terraform' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 0 │ +│ 28 │ 'terraform' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ +│ 29 │ 'terraform' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ +│ 30 │ 'terraform' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ +│ 31 │ 'terraform' │ 'ingress' │ [ 'openstack.machine' ] │ 0 │ +│ 32 │ 'terraform' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ +│ 33 │ 'terraform' │ 'openstack.machine' │ undefined │ 1 │ +│ 34 │ 'terraform' │ 'gcp.service' │ undefined │ 1 │ +│ 35 │ 'kubernetes' │ 'software.application' │ [ 'kubernetes' ] │ 1 │ +│ 36 │ 'kubernetes' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 0 │ +│ 37 │ 'kubernetes' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 1 │ +│ 38 │ 'kubernetes' │ 'ingress' │ [ 'kubernetes' ] │ 1 │ +│ 39 │ 'docker' │ 'software.application' │ [ 'docker.engine' ] │ 1 │ +│ 40 │ 'docker' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 0 │ +│ 41 │ 'docker' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 1 │ +└─────────┴──────────────┴────────────────────────┴─────────────────────────────────────────────┴─────────┘ + +Metrics relevant when modeling the different scenarios +┌─────────┬────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────┐ +│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ +├─────────┼────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────┤ +│ 0 │ 'EDMM GCP Variant' │ 1 │ 84 │ 0 │ 14 │ 253 │ │ +│ 1 │ 'EDMM OS Large Variant' │ 1 │ 114 │ 0 │ 18 │ 318 │ │ +│ 2 │ 'EDMM OS Medium Variant' │ 1 │ 114 │ 0 │ 18 │ 318 │ │ +│ 3 │ 'EDMM Total (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant)' │ 3 │ 312 │ 0 │ 50 │ 889 │ 'EDMM Total' │ +│ 4 │ 'VDMM Baseline Default' │ 1 │ 193 │ 8 │ 31 │ 520 │ │ +│ 5 │ 'VDMM+ Default Manual' │ 1 │ 147 │ 47 │ 31 │ 477 │ │ +│ 6 │ 'VDMM+ Default Automated Random' │ 1 │ 147 │ 24 │ 0 │ 415 │ │ +│ 7 │ 'VDMM+ Default Automated Counting' │ 1 │ 147 │ 24 │ 0 │ 416 │ │ +│ 8 │ 'VDMM+ Default Automated Quality' │ 1 │ 147 │ 24 │ 0 │ 412 │ │ +└─────────┴────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────┘ + +Qualities of the derived deployment models, i.e., the deployment variants, of the different scenarios ranging from bad (0) to good (1). +┌─────────┬──────────────┬────────┬─────────────┬─────────────┬────────────────┬─────────┬──────────────────┐ +│ (index) │ scenario │ expert │ non_expert │ random │ counting │ quality │ quality_counting │ +├─────────┼──────────────┼────────┼─────────────┼─────────────┼────────────────┼─────────┼──────────────────┤ +│ 0 │ 'gcp' │ 1 │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ 1 │ 1 │ +│ 1 │ 'kubernetes' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.92 ] │ 1 │ 1 │ +│ 2 │ 'os-large' │ 1 │ [ 0.33, 1 ] │ [ 0.33, 1 ] │ [ 0.42, 0.67 ] │ 1 │ 1 │ +│ 3 │ 'os-medium' │ 1 │ [ 0.33, 1 ] │ [ 0.33, 1 ] │ [ 0.42, 0.67 ] │ 1 │ 1 │ +└─────────┴──────────────┴────────┴─────────────┴─────────────┴────────────────┴─────────┴──────────────────┘ + +Metrics relevant when modeling the maintenance scenario of our case study +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────────────────┐ +│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────────────────┤ +│ 0 │ 'EDMM Kubernetes' │ 1 │ 88 │ 0 │ 13 │ 258 │ │ +│ 1 │ 'EDMM Total Maintenance (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant, EDMM Kubernetes)' │ 4 │ 400 │ 0 │ 63 │ 1147 │ 'EDMM Total Maintenance' │ +│ 2 │ 'VDMM Baseline Maintenance' │ 1 │ 287 │ 23 │ 43 │ 751 │ │ +│ 3 │ 'VDMM+ Maintenance Manual' │ 1 │ 174 │ 74 │ 43 │ 568 │ │ +│ 4 │ 'VDMM+ Maintenance Automated Random' │ 1 │ 174 │ 39 │ 0 │ 483 │ │ +│ 5 │ 'VDMM+ Maintenance Automated Counting' │ 1 │ 174 │ 39 │ 0 │ 484 │ │ +│ 6 │ 'VDMM+ Maintenance Automated Quality' │ 1 │ 174 │ 39 │ 0 │ 480 │ │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────────────────┘ + +From Default to Maintained (Absolut to previous) +┌─────────┬─────────────────────────────────────────────────────────────────────────┬──────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ +│ (index) │ scenario │ models_absolute_diff │ elements_absolute_diff │ conditions_absolute_diff │ technology_assignments_absolute_diff │ lines_of_code_absolute_diff │ +├─────────┼─────────────────────────────────────────────────────────────────────────┼──────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ +│ 0 │ 'EDMM Total Maintenance - EDMM Total' │ 1 │ 88 │ 0 │ 13 │ 258 │ +│ 1 │ 'VDMM Baseline Maintenance - VDMM Baseline Default' │ 0 │ 94 │ 15 │ 12 │ 231 │ +│ 2 │ 'VDMM+ Maintenance Manual - VDMM+ Default Manual' │ 0 │ 27 │ 27 │ 12 │ 91 │ +│ 3 │ 'VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality' │ 0 │ 27 │ 15 │ 0 │ 68 │ +└─────────┴─────────────────────────────────────────────────────────────────────────┴──────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ + +From Default to Maintained (Relative to change to baseline) +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ +│ (index) │ scenario │ elements_relative_diff │ conditions_relative_diff │ technology_assignments_relative_diff │ lines_of_code_relative_diff │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ +│ 0 │ '(VDMM+ Maintenance Manual - VDMM+ Default Manual) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.29 │ 1.8 │ 1 │ 0.39 │ +│ 1 │ '(VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.29 │ 1 │ 0 │ 0.29 │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ + +> Diff: artifacts \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-005.txt b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-005.txt new file mode 100644 index 0000000000..f808f636d0 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-005.txt @@ -0,0 +1,107 @@ + +The technology rules of our case study. Qualities range from bad (0) to good (1). +┌─────────┬──────────────┬────────────────────────┬─────────────────────────────────────────────┬─────────┐ +│ (index) │ Technology │ Component │ Hosting │ Quality │ +├─────────┼──────────────┼────────────────────────┼─────────────────────────────────────────────┼─────────┤ +│ 0 │ 'ansible' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ +│ 1 │ 'ansible' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ +│ 2 │ 'ansible' │ 'software.application' │ [ 'gcp.appengine' ] │ 0 │ +│ 3 │ 'ansible' │ 'software.application' │ [ 'openstack.machine' ] │ 1 │ +│ 4 │ 'ansible' │ 'docker.engine' │ [ 'openstack.machine' ] │ 1 │ +│ 5 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ +│ 6 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ +│ 7 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ +│ 8 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ +│ 9 │ 'ansible' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 1 │ +│ 10 │ 'ansible' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ +│ 11 │ 'ansible' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ +│ 12 │ 'ansible' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ +│ 13 │ 'ansible' │ 'ingress' │ [ 'openstack.machine' ] │ 1 │ +│ 14 │ 'ansible' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ +│ 15 │ 'ansible' │ 'openstack.machine' │ undefined │ 0.5 │ +│ 16 │ 'ansible' │ 'gcp.service' │ undefined │ 1 │ +│ 17 │ 'terraform' │ 'software.application' │ [ 'software.runtime', 'openstack.machine' ] │ 0 │ +│ 18 │ 'terraform' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ +│ 19 │ 'terraform' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ +│ 20 │ 'terraform' │ 'software.application' │ [ 'gcp.appengine' ] │ 1 │ +│ 21 │ 'terraform' │ 'software.application' │ [ 'openstack.machine' ] │ 0 │ +│ 22 │ 'terraform' │ 'docker.engine' │ [ 'openstack.machine' ] │ 0 │ +│ 23 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ +│ 24 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ +│ 25 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ +│ 26 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ +│ 27 │ 'terraform' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 0 │ +│ 28 │ 'terraform' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ +│ 29 │ 'terraform' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ +│ 30 │ 'terraform' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ +│ 31 │ 'terraform' │ 'ingress' │ [ 'openstack.machine' ] │ 0 │ +│ 32 │ 'terraform' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ +│ 33 │ 'terraform' │ 'openstack.machine' │ undefined │ 1 │ +│ 34 │ 'terraform' │ 'gcp.service' │ undefined │ 1 │ +│ 35 │ 'kubernetes' │ 'software.application' │ [ 'kubernetes' ] │ 1 │ +│ 36 │ 'kubernetes' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 0 │ +│ 37 │ 'kubernetes' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 1 │ +│ 38 │ 'kubernetes' │ 'ingress' │ [ 'kubernetes' ] │ 1 │ +│ 39 │ 'docker' │ 'software.application' │ [ 'docker.engine' ] │ 1 │ +│ 40 │ 'docker' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 0 │ +│ 41 │ 'docker' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 1 │ +└─────────┴──────────────┴────────────────────────┴─────────────────────────────────────────────┴─────────┘ + +Metrics relevant when modeling the different scenarios +┌─────────┬────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────┐ +│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ +├─────────┼────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────┤ +│ 0 │ 'EDMM GCP Variant' │ 1 │ 59 │ 0 │ 14 │ 205 │ │ +│ 1 │ 'EDMM OS Large Variant' │ 1 │ 88 │ 0 │ 18 │ 267 │ │ +│ 2 │ 'EDMM OS Medium Variant' │ 1 │ 88 │ 0 │ 18 │ 267 │ │ +│ 3 │ 'EDMM Total (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant)' │ 3 │ 235 │ 0 │ 50 │ 739 │ 'EDMM Total' │ +│ 4 │ 'VDMM Baseline Default' │ 1 │ 146 │ 16 │ 31 │ 450 │ │ +│ 5 │ 'VDMM+ Default Manual' │ 1 │ 113 │ 31 │ 31 │ 406 │ │ +│ 6 │ 'VDMM+ Default Automated Random' │ 1 │ 113 │ 8 │ 0 │ 344 │ │ +│ 7 │ 'VDMM+ Default Automated Counting' │ 1 │ 113 │ 8 │ 0 │ 345 │ │ +│ 8 │ 'VDMM+ Default Automated Quality' │ 1 │ 113 │ 8 │ 0 │ 341 │ │ +└─────────┴────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────┘ + +Qualities of the derived deployment models, i.e., the deployment variants, of the different scenarios ranging from bad (0) to good (1). +┌─────────┬──────────────┬────────┬─────────────┬─────────────┬────────────────┬─────────┬──────────────────┐ +│ (index) │ scenario │ expert │ non_expert │ random │ counting │ quality │ quality_counting │ +├─────────┼──────────────┼────────┼─────────────┼─────────────┼────────────────┼─────────┼──────────────────┤ +│ 0 │ 'gcp' │ 1 │ [ 0.27, 1 ] │ [ 0.27, 1 ] │ [ 0.27, 1 ] │ 1 │ 1 │ +│ 1 │ 'kubernetes' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.93 ] │ 1 │ 1 │ +│ 2 │ 'os-large' │ 1 │ [ 0.34, 1 ] │ [ 0.34, 1 ] │ [ 0.42, 0.66 ] │ 1 │ 1 │ +│ 3 │ 'os-medium' │ 1 │ [ 0.34, 1 ] │ [ 0.34, 1 ] │ [ 0.42, 0.66 ] │ 1 │ 1 │ +└─────────┴──────────────┴────────┴─────────────┴─────────────┴────────────────┴─────────┴──────────────────┘ + +Metrics relevant when modeling the maintenance scenario of our case study +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────────────────┐ +│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────────────────┤ +│ 0 │ 'EDMM Kubernetes' │ 1 │ 68 │ 0 │ 13 │ 224 │ │ +│ 1 │ 'EDMM Total Maintenance (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant, EDMM Kubernetes)' │ 4 │ 303 │ 0 │ 63 │ 963 │ 'EDMM Total Maintenance' │ +│ 2 │ 'VDMM Baseline Maintenance' │ 1 │ 228 │ 35 │ 46 │ 671 │ │ +│ 3 │ 'VDMM+ Maintenance Manual' │ 1 │ 146 │ 51 │ 46 │ 519 │ │ +│ 4 │ 'VDMM+ Maintenance Automated Random' │ 1 │ 146 │ 13 │ 0 │ 428 │ │ +│ 5 │ 'VDMM+ Maintenance Automated Counting' │ 1 │ 146 │ 13 │ 0 │ 429 │ │ +│ 6 │ 'VDMM+ Maintenance Automated Quality' │ 1 │ 146 │ 13 │ 0 │ 425 │ │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────────────────┘ + +From Default to Maintained (Absolut to previous) +┌─────────┬─────────────────────────────────────────────────────────────────────────┬──────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ +│ (index) │ scenario │ models_absolute_diff │ elements_absolute_diff │ conditions_absolute_diff │ technology_assignments_absolute_diff │ lines_of_code_absolute_diff │ +├─────────┼─────────────────────────────────────────────────────────────────────────┼──────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ +│ 0 │ 'EDMM Total Maintenance - EDMM Total' │ 1 │ 68 │ 0 │ 13 │ 224 │ +│ 1 │ 'VDMM Baseline Maintenance - VDMM Baseline Default' │ 0 │ 82 │ 19 │ 15 │ 221 │ +│ 2 │ 'VDMM+ Maintenance Manual - VDMM+ Default Manual' │ 0 │ 33 │ 20 │ 15 │ 113 │ +│ 3 │ 'VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality' │ 0 │ 33 │ 5 │ 0 │ 84 │ +└─────────┴─────────────────────────────────────────────────────────────────────────┴──────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ + +From Default to Maintained (Relative to change to baseline) +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ +│ (index) │ scenario │ elements_relative_diff │ conditions_relative_diff │ technology_assignments_relative_diff │ lines_of_code_relative_diff │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ +│ 0 │ '(VDMM+ Maintenance Manual - VDMM+ Default Manual) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.4 │ 1.05 │ 1 │ 0.51 │ +│ 1 │ '(VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.4 │ 0.26 │ 0 │ 0.38 │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ + +> Starting Point: Docker on VM; Diff: payment properties already in default and new analytical component with analytical properties in maintenance +> CURRENTLY SELECTED \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-006.txt b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-006.txt new file mode 100644 index 0000000000..1d00aa1024 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-006.txt @@ -0,0 +1,107 @@ + +The technology rules of our case study. Qualities range from bad (0) to good (1). +┌─────────┬──────────────┬────────────────────────┬─────────────────────────────────────────────┬─────────┐ +│ (index) │ Technology │ Component │ Hosting │ Quality │ +├─────────┼──────────────┼────────────────────────┼─────────────────────────────────────────────┼─────────┤ +│ 0 │ 'ansible' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ +│ 1 │ 'ansible' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ +│ 2 │ 'ansible' │ 'software.application' │ [ 'gcp.appengine' ] │ 0 │ +│ 3 │ 'ansible' │ 'software.application' │ [ 'openstack.machine' ] │ 1 │ +│ 4 │ 'ansible' │ 'docker.engine' │ [ 'openstack.machine' ] │ 1 │ +│ 5 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ +│ 6 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ +│ 7 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ +│ 8 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ +│ 9 │ 'ansible' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 1 │ +│ 10 │ 'ansible' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ +│ 11 │ 'ansible' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ +│ 12 │ 'ansible' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ +│ 13 │ 'ansible' │ 'ingress' │ [ 'openstack.machine' ] │ 1 │ +│ 14 │ 'ansible' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ +│ 15 │ 'ansible' │ 'openstack.machine' │ undefined │ 0.5 │ +│ 16 │ 'ansible' │ 'gcp.service' │ undefined │ 1 │ +│ 17 │ 'terraform' │ 'software.application' │ [ 'software.runtime', 'openstack.machine' ] │ 0 │ +│ 18 │ 'terraform' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ +│ 19 │ 'terraform' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ +│ 20 │ 'terraform' │ 'software.application' │ [ 'gcp.appengine' ] │ 1 │ +│ 21 │ 'terraform' │ 'software.application' │ [ 'openstack.machine' ] │ 0 │ +│ 22 │ 'terraform' │ 'docker.engine' │ [ 'openstack.machine' ] │ 0 │ +│ 23 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ +│ 24 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ +│ 25 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ +│ 26 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ +│ 27 │ 'terraform' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 0 │ +│ 28 │ 'terraform' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ +│ 29 │ 'terraform' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ +│ 30 │ 'terraform' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ +│ 31 │ 'terraform' │ 'ingress' │ [ 'openstack.machine' ] │ 0 │ +│ 32 │ 'terraform' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ +│ 33 │ 'terraform' │ 'openstack.machine' │ undefined │ 1 │ +│ 34 │ 'terraform' │ 'gcp.service' │ undefined │ 1 │ +│ 35 │ 'kubernetes' │ 'software.application' │ [ 'kubernetes' ] │ 1 │ +│ 36 │ 'kubernetes' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 0 │ +│ 37 │ 'kubernetes' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 1 │ +│ 38 │ 'kubernetes' │ 'ingress' │ [ 'kubernetes' ] │ 1 │ +│ 39 │ 'docker' │ 'software.application' │ [ 'docker.engine' ] │ 1 │ +│ 40 │ 'docker' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 0 │ +│ 41 │ 'docker' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 1 │ +└─────────┴──────────────┴────────────────────────┴─────────────────────────────────────────────┴─────────┘ + +Metrics relevant when modeling the different scenarios +┌─────────┬────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────┐ +│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ +├─────────┼────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────┤ +│ 0 │ 'EDMM GCP Variant' │ 1 │ 63 │ 0 │ 14 │ 211 │ │ +│ 1 │ 'EDMM OS Large Variant' │ 1 │ 92 │ 0 │ 18 │ 273 │ │ +│ 2 │ 'EDMM OS Medium Variant' │ 1 │ 92 │ 0 │ 18 │ 273 │ │ +│ 3 │ 'EDMM Total (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant)' │ 3 │ 247 │ 0 │ 50 │ 757 │ 'EDMM Total' │ +│ 4 │ 'VDMM Baseline Default' │ 1 │ 154 │ 16 │ 31 │ 462 │ │ +│ 5 │ 'VDMM+ Default Manual' │ 1 │ 117 │ 31 │ 31 │ 412 │ │ +│ 6 │ 'VDMM+ Default Automated Random' │ 1 │ 117 │ 8 │ 0 │ 350 │ │ +│ 7 │ 'VDMM+ Default Automated Counting' │ 1 │ 117 │ 8 │ 0 │ 351 │ │ +│ 8 │ 'VDMM+ Default Automated Quality' │ 1 │ 117 │ 8 │ 0 │ 347 │ │ +└─────────┴────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────┘ + +Qualities of the derived deployment models, i.e., the deployment variants, of the different scenarios ranging from bad (0) to good (1). +┌─────────┬──────────────┬────────┬─────────────┬─────────────┬────────────────┬─────────┬──────────────────┐ +│ (index) │ scenario │ expert │ non_expert │ random │ counting │ quality │ quality_counting │ +├─────────┼──────────────┼────────┼─────────────┼─────────────┼────────────────┼─────────┼──────────────────┤ +│ 0 │ 'gcp' │ 1 │ [ 0.27, 1 ] │ [ 0.27, 1 ] │ [ 0.27, 1 ] │ 1 │ 1 │ +│ 1 │ 'kubernetes' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.93 ] │ 1 │ 1 │ +│ 2 │ 'os-large' │ 1 │ [ 0.34, 1 ] │ [ 0.34, 1 ] │ [ 0.42, 0.66 ] │ 1 │ 1 │ +│ 3 │ 'os-medium' │ 1 │ [ 0.34, 1 ] │ [ 0.34, 1 ] │ [ 0.42, 0.66 ] │ 1 │ 1 │ +└─────────┴──────────────┴────────┴─────────────┴─────────────┴────────────────┴─────────┴──────────────────┘ + +Metrics relevant when modeling the maintenance scenario of our case study +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────────────────┐ +│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────────────────┤ +│ 0 │ 'EDMM Kubernetes' │ 1 │ 72 │ 0 │ 13 │ 230 │ │ +│ 1 │ 'EDMM Total Maintenance (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant, EDMM Kubernetes)' │ 4 │ 319 │ 0 │ 63 │ 987 │ 'EDMM Total Maintenance' │ +│ 2 │ 'VDMM Baseline Maintenance' │ 1 │ 240 │ 35 │ 46 │ 689 │ │ +│ 3 │ 'VDMM+ Maintenance Manual' │ 1 │ 150 │ 51 │ 46 │ 525 │ │ +│ 4 │ 'VDMM+ Maintenance Automated Random' │ 1 │ 150 │ 13 │ 0 │ 434 │ │ +│ 5 │ 'VDMM+ Maintenance Automated Counting' │ 1 │ 150 │ 13 │ 0 │ 435 │ │ +│ 6 │ 'VDMM+ Maintenance Automated Quality' │ 1 │ 150 │ 13 │ 0 │ 431 │ │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────────────────┘ + +From Default to Maintained (Absolut to previous) +┌─────────┬─────────────────────────────────────────────────────────────────────────┬──────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ +│ (index) │ scenario │ models_absolute_diff │ elements_absolute_diff │ conditions_absolute_diff │ technology_assignments_absolute_diff │ lines_of_code_absolute_diff │ +├─────────┼─────────────────────────────────────────────────────────────────────────┼──────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ +│ 0 │ 'EDMM Total Maintenance - EDMM Total' │ 1 │ 72 │ 0 │ 13 │ 230 │ +│ 1 │ 'VDMM Baseline Maintenance - VDMM Baseline Default' │ 0 │ 86 │ 19 │ 15 │ 227 │ +│ 2 │ 'VDMM+ Maintenance Manual - VDMM+ Default Manual' │ 0 │ 33 │ 20 │ 15 │ 113 │ +│ 3 │ 'VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality' │ 0 │ 33 │ 5 │ 0 │ 84 │ +└─────────┴─────────────────────────────────────────────────────────────────────────┴──────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ + +From Default to Maintained (Relative to change to baseline) +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ +│ (index) │ scenario │ elements_relative_diff │ conditions_relative_diff │ technology_assignments_relative_diff │ lines_of_code_relative_diff │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ +│ 0 │ '(VDMM+ Maintenance Manual - VDMM+ Default Manual) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.38 │ 1.05 │ 1 │ 0.5 │ +│ 1 │ '(VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.38 │ 0.26 │ 0 │ 0.37 │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ + +> Starting Point: 005; Diff: payment properties also at frontend and checkout +> Comment: little value, configuration should happen automatically due to specialized tosca node types \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-007.txt b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-007.txt new file mode 100644 index 0000000000..c9a4a01dcf --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-007.txt @@ -0,0 +1,116 @@ + +The technology rules of our case study. Qualities range from bad (0) to good (1). +┌─────────┬──────────────┬────────────────────────┬───────────────────────────────────────┬─────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ (index) │ Technology │ Component │ Hosting │ Quality │ Comment │ +├─────────┼──────────────┼────────────────────────┼───────────────────────────────────────┼─────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ 0 │ 'ansible' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ 'Docker is more specialized.' │ +│ 1 │ 'ansible' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ 'Kubernetes is more specialized.' │ +│ 2 │ 'ansible' │ 'software.application' │ [ 'gcp.cloudrun' ] │ 0 │ 'Custom module with imperative parts, while Terraform provides a declarative module.' │ +│ 3 │ 'ansible' │ 'software.application' │ [ 'openstack.machine' ] │ 1 │ 'Primary use case due to the specialization of Ansible.' │ +│ 4 │ 'ansible' │ 'docker.engine' │ [ 'openstack.machine' ] │ 1 │ 'Primary use case due to the specialization of Ansible.' │ +│ 5 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ 'Primary use case due to the specialization of Ansible.' │ +│ 6 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ 'Primary use case due to the specialization of Ansible.' │ +│ 7 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ 'Primary use case due to the specialization of Ansible.' │ +│ 8 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ undefined │ +│ 9 │ 'ansible' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 1 │ 'Primary use case due to the specialization of Ansible.' │ +│ 10 │ 'ansible' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ 'Docker is more specialized.' │ +│ 11 │ 'ansible' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ 'Kubernetes is more specialized.' │ +│ 12 │ 'ansible' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ undefined │ +│ 13 │ 'ansible' │ 'ingress' │ [ 'openstack.machine' ] │ 1 │ 'Primary use case due to the specialization of Ansible.' │ +│ 14 │ 'ansible' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ 'Kubernetes is more specialized.' │ +│ 15 │ 'ansible' │ 'openstack.machine' │ undefined │ 0.5 │ 'Terraform is more specialized.' │ +│ 16 │ 'ansible' │ 'gcp.service' │ undefined │ 1 │ undefined │ +│ 17 │ 'terraform' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ 'Docker is more specialized.' │ +│ 18 │ 'terraform' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ 'Kubernetes is more specialized.' │ +│ 19 │ 'terraform' │ 'software.application' │ [ 'gcp.cloudrun' ] │ 1 │ 'Terraform provides a declarative module.' │ +│ 20 │ 'terraform' │ 'software.application' │ [ 'openstack.machine' ] │ 0 │ 'Ansible is more specialized. Also using Remote-Exec Executor is a "last resort".' │ +│ 21 │ 'terraform' │ 'docker.engine' │ [ 'openstack.machine' ] │ 0 │ 'Ansible is more specialized. Also using Remote-Exec Executor is a "last resort".' │ +│ 22 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ 'Terraform provides a declarative module.' │ +│ 23 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ 'Terraform provides a declarative module.' │ +│ 24 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ 'Terraform provides a declarative module.' │ +│ 25 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ 'Terraform provides a declarative module.' │ +│ 26 │ 'terraform' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 0 │ 'Ansible is more specialized. Also using Remote-Exec Executor is a "last resort".' │ +│ 27 │ 'terraform' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ 'Docker is more specialized.' │ +│ 28 │ 'terraform' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ 'Kubernetes is more specialized.' │ +│ 29 │ 'terraform' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ 'Terraform provides a declarative module.' │ +│ 30 │ 'terraform' │ 'ingress' │ [ 'openstack.machine' ] │ 0 │ 'Ansible is more specialized. Also using Remote-Exec Executor is a "last resort".' │ +│ 31 │ 'terraform' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ 'Kubernetes is more specialized.' │ +│ 32 │ 'terraform' │ 'openstack.machine' │ undefined │ 1 │ 'Terraform provides a declarative module.' │ +│ 33 │ 'terraform' │ 'gcp.service' │ undefined │ 1 │ 'Terraform provides a declarative module.' │ +│ 34 │ 'kubernetes' │ 'software.application' │ [ 'kubernetes' ] │ 1 │ 'Kubernetes is the underlying technology.' │ +│ 35 │ 'kubernetes' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 0 │ 'Kubernetes Job with imperative parts, while declarative other technologies provide declarative modules.' │ +│ 36 │ 'kubernetes' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 1 │ 'Kubernetes is the underlying technology.' │ +│ 37 │ 'kubernetes' │ 'ingress' │ [ 'kubernetes' ] │ 1 │ 'Kubernetes is the underlying technology.' │ +│ 38 │ 'docker' │ 'software.application' │ [ 'docker.engine' ] │ 1 │ 'Docker is the underlying technology.' │ +│ 39 │ 'docker' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 0 │ 'One-time use docker container ("fake Kubernetes job") with imperative parts, while declarative other technologies provide declarative modules.' │ +│ 40 │ 'docker' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 1 │ 'Docker is the underlying technology.' │ +└─────────┴──────────────┴────────────────────────┴───────────────────────────────────────┴─────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + +Metrics relevant when modeling the different scenarios +┌─────────┬────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────┐ +│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ +├─────────┼────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────┤ +│ 0 │ 'EDMM GCP Variant' │ 1 │ 59 │ 0 │ 14 │ 205 │ │ +│ 1 │ 'EDMM OS Large Variant' │ 1 │ 88 │ 0 │ 18 │ 267 │ │ +│ 2 │ 'EDMM OS Medium Variant' │ 1 │ 88 │ 0 │ 18 │ 267 │ │ +│ 3 │ 'EDMM Total (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant)' │ 3 │ 235 │ 0 │ 50 │ 739 │ 'EDMM Total' │ +│ 4 │ 'VDMM Baseline Original' │ 1 │ 146 │ 16 │ 31 │ 450 │ │ +│ 5 │ 'VDMM+ Original Manual' │ 1 │ 113 │ 31 │ 31 │ 406 │ │ +│ 6 │ 'VDMM+ Original Automated Random' │ 1 │ 113 │ 8 │ 0 │ 344 │ │ +│ 7 │ 'VDMM+ Original Automated Counting' │ 1 │ 113 │ 8 │ 0 │ 345 │ │ +│ 8 │ 'VDMM+ Original Automated Quality' │ 1 │ 113 │ 8 │ 0 │ 341 │ │ +└─────────┴────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────┘ + +Diff when modeling the different original scenarios +┌─────────┬──────────────────────────────────────────────────────────────┬─────────────────┬─────────────────┬───────────────────┬───────────────────┬─────────────────────┬─────────────────────┬─────────────────────────────────┬─────────────────────────────────┬────────────────────────┬────────────────────────┐ +│ (index) │ scenario │ models_abs_diff │ models_rel_diff │ elements_abs_diff │ elements_rel_diff │ conditions_abs_diff │ conditions_rel_diff │ technology_assignments_abs_diff │ technology_assignments_rel_diff │ lines_of_code_abs_diff │ lines_of_code_rel_diff │ +├─────────┼──────────────────────────────────────────────────────────────┼─────────────────┼─────────────────┼───────────────────┼───────────────────┼─────────────────────┼─────────────────────┼─────────────────────────────────┼─────────────────────────────────┼────────────────────────┼────────────────────────┤ +│ 0 │ 'VDMM Baseline Original - EDMM Total' │ -2 │ 0.33 │ -89 │ 0.62 │ 16 │ Infinity │ -19 │ 0.62 │ -289 │ 0.61 │ +│ 1 │ 'VDMM+ Original Manual - VDMM Baseline Original' │ 0 │ 1 │ -33 │ 0.77 │ 15 │ 1.94 │ 0 │ 1 │ -44 │ 0.9 │ +│ 2 │ 'VDMM+ Original Automated Random - VDMM Baseline Original' │ 0 │ 1 │ -33 │ 0.77 │ -8 │ 0.5 │ -31 │ 0 │ -106 │ 0.76 │ +│ 3 │ 'VDMM+ Original Automated Counting - VDMM Baseline Original' │ 0 │ 1 │ -33 │ 0.77 │ -8 │ 0.5 │ -31 │ 0 │ -105 │ 0.77 │ +│ 4 │ 'VDMM+ Original Automated Quality - VDMM Baseline Original' │ 0 │ 1 │ -33 │ 0.77 │ -8 │ 0.5 │ -31 │ 0 │ -109 │ 0.76 │ +└─────────┴──────────────────────────────────────────────────────────────┴─────────────────┴─────────────────┴───────────────────┴───────────────────┴─────────────────────┴─────────────────────┴─────────────────────────────────┴─────────────────────────────────┴────────────────────────┴────────────────────────┘ + +Qualities of the derived deployment models, i.e., the deployment variants, of the different scenarios ranging from bad (0) to good (1). +┌─────────┬──────────────┬────────┬─────────────┬─────────────┬────────────────┬─────────┬──────────────────┐ +│ (index) │ scenario │ expert │ non_expert │ random │ counting │ quality │ quality_counting │ +├─────────┼──────────────┼────────┼─────────────┼─────────────┼────────────────┼─────────┼──────────────────┤ +│ 0 │ 'gcp' │ 1 │ [ 0.27, 1 ] │ [ 0.27, 1 ] │ [ 0.27, 1 ] │ 1 │ 1 │ +│ 1 │ 'kubernetes' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.93 ] │ 1 │ 1 │ +│ 2 │ 'os-large' │ 1 │ [ 0.34, 1 ] │ [ 0.34, 1 ] │ [ 0.42, 0.66 ] │ 1 │ 1 │ +│ 3 │ 'os-medium' │ 1 │ [ 0.34, 1 ] │ [ 0.34, 1 ] │ [ 0.42, 0.66 ] │ 1 │ 1 │ +└─────────┴──────────────┴────────┴─────────────┴─────────────┴────────────────┴─────────┴──────────────────┘ + +Metrics relevant when modeling the maintenance scenario of our case study +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────────────────┐ +│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────────────────┤ +│ 0 │ 'EDMM Kubernetes' │ 1 │ 68 │ 0 │ 13 │ 224 │ │ +│ 1 │ 'EDMM Total Maintenance (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant, EDMM Kubernetes)' │ 4 │ 303 │ 0 │ 63 │ 963 │ 'EDMM Total Maintenance' │ +│ 2 │ 'VDMM Baseline Maintenance' │ 1 │ 228 │ 35 │ 46 │ 671 │ │ +│ 3 │ 'VDMM+ Maintenance Manual' │ 1 │ 146 │ 51 │ 46 │ 519 │ │ +│ 4 │ 'VDMM+ Maintenance Automated Random' │ 1 │ 146 │ 13 │ 0 │ 428 │ │ +│ 5 │ 'VDMM+ Maintenance Automated Counting' │ 1 │ 146 │ 13 │ 0 │ 429 │ │ +│ 6 │ 'VDMM+ Maintenance Automated Quality' │ 1 │ 146 │ 13 │ 0 │ 425 │ │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────────────────┘ + +From Original to Maintained (Absolut to previous) (Absolute) +┌─────────┬──────────────────────────────────────────────────────────────────────────┬─────────────────┬───────────────────┬─────────────────────┬─────────────────────────────────┬────────────────────────┐ +│ (index) │ scenario │ models_abs_diff │ elements_abs_diff │ conditions_abs_diff │ technology_assignments_abs_diff │ lines_of_code_abs_diff │ +├─────────┼──────────────────────────────────────────────────────────────────────────┼─────────────────┼───────────────────┼─────────────────────┼─────────────────────────────────┼────────────────────────┤ +│ 0 │ 'EDMM Total Maintenance - EDMM Total' │ 1 │ 68 │ 0 │ 13 │ 224 │ +│ 1 │ 'VDMM Baseline Maintenance - VDMM Baseline Original' │ 0 │ 82 │ 19 │ 15 │ 221 │ +│ 2 │ 'VDMM+ Maintenance Manual - VDMM+ Original Manual' │ 0 │ 33 │ 20 │ 15 │ 113 │ +│ 3 │ 'VDMM+ Maintenance Automated Quality - VDMM+ Original Automated Quality' │ 0 │ 33 │ 5 │ 0 │ 84 │ +└─────────┴──────────────────────────────────────────────────────────────────────────┴─────────────────┴───────────────────┴─────────────────────┴─────────────────────────────────┴────────────────────────┘ + +From Original to Maintained (Relative to change to baseline) +┌─────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬───────────────────┬─────────────────────┬─────────────────────────────────┬────────────────────────┐ +│ (index) │ scenario │ elements_rel_diff │ conditions_rel_diff │ technology_assignments_rel_diff │ lines_of_code_rel_diff │ +├─────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────────┼─────────────────────┼─────────────────────────────────┼────────────────────────┤ +│ 0 │ '(VDMM+ Maintenance Manual - VDMM+ Original Manual) / (VDMM Baseline Maintenance - VDMM Baseline Original)' │ 0.4 │ 1.05 │ 1 │ 0.51 │ +│ 1 │ '(VDMM+ Maintenance Automated Quality - VDMM+ Original Automated Quality) / (VDMM Baseline Maintenance - VDMM Baseline Original)' │ 0.4 │ 0.26 │ 0 │ 0.38 │ +└─────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴───────────────────┴─────────────────────┴─────────────────────────────────┴────────────────────────┘ + +> 006 but with enriched data diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study.sh new file mode 100755 index 0000000000..d8b7a00971 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +# Load configuration +source configuration.sh + +# Study +$VINTNER study technology --application boutique --experimental diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/swap-lib.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/swap-lib.sh new file mode 100755 index 0000000000..3c6c742fdf --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/swap-lib.sh @@ -0,0 +1,16 @@ +#! /usr/bin/bash +set -e + +# Set working directory +cd "$(dirname "$0")" + +FS="/c/Users" +if [[ "${OSTYPE}" == "linux-gnu" ]]; then + FS="/home" +fi + +# Delete lib in instance +rm -rf ${FS}/stoetzms/.opentosca_vintner/instances/technology-gcp/data/ensemble/lib + +# Copy local lib into instance +cp -R ../lib ${FS}/stoetzms/.opentosca_vintner/instances/technology-gcp/data/ensemble diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/undeploy.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/undeploy.sh new file mode 100755 index 0000000000..799765e670 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/undeploy.sh @@ -0,0 +1,11 @@ +#! /usr/bin/bash +set -e + +# Set working directory +cd "$(dirname "$0")" + +# Load configuration +source configuration.sh + +# Undeploy application +$VINTNER instances undeploy --instance ${TEMPLATE_NAME} diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/unimplement.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/unimplement.sh new file mode 100755 index 0000000000..f92b98c181 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/unimplement.sh @@ -0,0 +1,9 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +# Pull dependencies +$VINTNER technologies clean --lib ${TEMPLATE_DIR}/lib + diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/study.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/study.yaml new file mode 100644 index 0000000000..4b4ad8fb49 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/study.yaml @@ -0,0 +1,6 @@ +study: technology +originals: + - gcp + - kubernetes + - os-medium + - os-large diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/expected.yaml new file mode 100644 index 0000000000..a72ce7bcf1 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/expected.yaml @@ -0,0 +1,310 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + + dbms_password: + type: string + + gcp_region: + type: string + + gcp_service_account_file: + type: string + + gcp_project: + type: string + + node_templates: + ################################################### + # + # Frontend + # + ################################################### + + frontend_component: + type: frontend.component~service.application#docker.image::terraform@gcp.cloudrun + properties: + application_name: frontend + application_port: 8080 + application_protocol: http + disable_profiler: '1' + CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} + CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} + SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} + CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} + PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} + RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} + AD_SERVICE_ADDR: {eval: '.::.requirements::[.name=advertisement]::.target::application_endpoint'} + optional_payment_feature: 'false' + premium_payment_feature: 'false' + SHOPPING_ASSISTANT_SERVICE_ADDR: 'required-but-not-used' + requirements: + - checkout: checkout_component + - currency: currency_component + - shipping: shipping_component + - cart: cart_component + - product: product_component + - recommendation: recommendation_component + - advertisement: advertisement_component + - host: gcp_cloudrun + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-frontend:v8 + + ################################################### + # + # Checkout + # + ################################################### + + checkout_component: + type: checkout.component~service.application#docker.image::terraform@gcp.cloudrun + properties: + application_name: checkout + application_port: 7003 + application_protocol: grpc + disable_profiler: '1' + PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} + SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} + PAYMENT_SERVICE_ADDR: {eval: '.::.requirements::[.name=payment]::.target::application_endpoint'} + EMAIL_SERVICE_ADDR: {eval: '.::.requirements::[.name=email]::.target::application_endpoint'} + CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} + CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} + optional_payment_feature: 'false' + premium_payment_feature: 'false' + requirements: + - email: email_component + - payment: payment_component + - currency: currency_component + - shipping: shipping_component + - cart: cart_component + - product: product_component + - host: gcp_cloudrun + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-checkout:v8 + + ################################################### + # + # Email + # + ################################################### + + email_component: + type: email.component~service.application#docker.image::terraform@gcp.cloudrun + properties: + application_name: email + application_port: 7005 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: gcp_cloudrun + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-email:v8 + + ################################################### + # + # Payment + # + ################################################### + + payment_component: + type: payment.component~service.application#docker.image::terraform@gcp.cloudrun + properties: + application_name: payment + application_port: 7006 + application_protocol: grpc + disable_profiler: '1' + optional_payment_feature: 'false' + premium_payment_feature: 'false' + requirements: + - host: gcp_cloudrun + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-payment:v8 + + ################################################### + # + # Currency + # + ################################################### + + currency_component: + type: currency.component~service.application#docker.image::terraform@gcp.cloudrun + properties: + application_name: currency + application_port: 7004 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: gcp_cloudrun + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-currency:v8 + + ################################################### + # + # Shipping + # + ################################################### + + shipping_component: + type: shipping.component~service.application#docker.image::terraform@gcp.cloudrun + properties: + application_name: shipping + application_port: 7009 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: gcp_cloudrun + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-shipping:v8 + + ################################################### + # + # Cart + # + ################################################### + + cart_component: + type: cart.component~service.application#docker.image::terraform@gcp.cloudrun + properties: + application_name: cart + application_port: 7070 + application_protocol: grpc + disable_profiler: '1' + mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} + mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} + mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} + mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} + mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} + mysql_table: 'cart' + mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} + + requirements: + - database: cart_database + - host: gcp_cloudrun + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-cart:v8 + + cart_database: + type: mysql.database~mysql.database::terraform@mysql.dbms->gcp.cloudsql + properties: + database_name: cart + database_user: cart + database_password: {get_input: database_password} + requirements: + - host: cart_dbms + + cart_dbms: + type: mysql.dbms~mysql.dbms#dbms.image::terraform@gcp.cloudsql + properties: + dbms_name: unfurl-technology-boutique-cart-dbms + dbms_password: {get_input: dbms_password} + requirements: + - host: gcp_cloudsql + artifacts: + dbms_image: + type: dbms.image + file: 5.7 + + ################################################### + # + # Product + # + ################################################### + + product_component: + type: product.component~service.application#docker.image::terraform@gcp.cloudrun + properties: + application_name: product + application_port: 7007 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: gcp_cloudrun + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-product:v8 + + ################################################### + # + # Recommendation + # + ################################################### + + recommendation_component: + type: recommendation.component~service.application#docker.image::terraform@gcp.cloudrun + properties: + application_name: recommendation + application_port: 7008 + application_protocol: grpc + disable_profiler: '1' + PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} + requirements: + - product: product_component + - host: gcp_cloudrun + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-recommendation:v8 + + ################################################### + # + # Advertisement + # + ################################################### + + advertisement_component: + type: advertisement.component~service.application#docker.image::terraform@gcp.cloudrun + properties: + application_name: advertisement + application_port: 7000 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: gcp_cloudrun + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-advertisement:v8 + + ################################################### + # + # GCP + # + ################################################### + + gcp_cloudrun: + type: gcp.cloudrun~gcp.service::terraform + requirements: + - host: gcp_provider + + gcp_cloudsql: + type: gcp.cloudsql~gcp.service::terraform + requirements: + - host: gcp_provider + + gcp_provider: + type: gcp.provider + properties: + gcp_region: {get_input: gcp_region} + gcp_service_account_file: {get_input: gcp_service_account_file} + gcp_project: {get_input: gcp_project} diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/inputs.yaml new file mode 100644 index 0000000000..f9aae7ddda --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/inputs.yaml @@ -0,0 +1 @@ +env: GCP diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/test.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/test.yaml new file mode 100644 index 0000000000..ec7309948d --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/test.yaml @@ -0,0 +1,21 @@ +merge: + topology_template: + node_templates: + analytics_component: + type: analytics.component~service.application#docker.image::terraform@gcp.cloudrun + properties: + application_name: analytics + application_port: 7001 + application_protocol: grpc + CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} + RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} + optional_analytical_feature: 'false' + premium_analytical_feature: 'false' + requirements: + - checkout: checkout_component + - recommendation: recommendation_component + - host: gcp_cloudrun + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-analytics:v8 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/expected.yaml new file mode 100644 index 0000000000..aedf7cb34d --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/expected.yaml @@ -0,0 +1,340 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + + dbms_password: + type: string + + k8s_host: + type: string + + k8s_ca_cert_file: + type: string + + k8s_client_cert_file: + type: string + + k8s_client_key_file: + type: string + + node_templates: + ################################################### + # + # Frontend + # + ################################################### + + frontend_component: + type: frontend.component~service.application#docker.image::kubernetes@kubernetes.cluster + properties: + application_name: frontend + application_port: 8080 + application_protocol: http + disable_profiler: '1' + CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} + CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} + SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} + CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} + PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} + RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} + AD_SERVICE_ADDR: {eval: '.::.requirements::[.name=advertisement]::.target::application_endpoint'} + optional_payment_feature: 'false' + premium_payment_feature: 'false' + SHOPPING_ASSISTANT_SERVICE_ADDR: 'required-but-not-used' + requirements: + - checkout: checkout_component + - currency: currency_component + - shipping: shipping_component + - cart: cart_component + - product: product_component + - recommendation: recommendation_component + - advertisement: advertisement_component + - host: kubernetes_cluster + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-frontend:v8 + + frontend_ingress: + type: ingress~ingress::kubernetes@kubernetes.cluster + requirements: + - application: frontend_component + - host: kubernetes_cluster + + ################################################### + # + # Checkout + # + ################################################### + + checkout_component: + type: checkout.component~service.application#docker.image::kubernetes@kubernetes.cluster + properties: + application_name: checkout + application_port: 7003 + application_protocol: grpc + disable_profiler: '1' + PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} + SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} + PAYMENT_SERVICE_ADDR: {eval: '.::.requirements::[.name=payment]::.target::application_endpoint'} + EMAIL_SERVICE_ADDR: {eval: '.::.requirements::[.name=email]::.target::application_endpoint'} + CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} + CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} + optional_payment_feature: 'false' + premium_payment_feature: 'false' + requirements: + - email: email_component + - payment: payment_component + - currency: currency_component + - shipping: shipping_component + - cart: cart_component + - product: product_component + - host: kubernetes_cluster + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-checkout:v8 + + ################################################### + # + # Email + # + ################################################### + + email_component: + type: email.component~service.application#docker.image::kubernetes@kubernetes.cluster + properties: + application_name: email + application_port: 7005 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: kubernetes_cluster + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-email:v8 + + ################################################### + # + # Payment + # + ################################################### + + payment_component: + type: payment.component~service.application#docker.image::kubernetes@kubernetes.cluster + properties: + application_name: payment + application_port: 7006 + application_protocol: grpc + disable_profiler: '1' + optional_payment_feature: 'false' + premium_payment_feature: 'false' + requirements: + - host: kubernetes_cluster + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-payment:v8 + + ################################################### + # + # Currency + # + ################################################### + + currency_component: + type: currency.component~service.application#docker.image::kubernetes@kubernetes.cluster + properties: + application_name: currency + application_port: 7004 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: kubernetes_cluster + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-currency:v8 + + ################################################### + # + # Shipping + # + ################################################### + + shipping_component: + type: shipping.component~service.application#docker.image::kubernetes@kubernetes.cluster + properties: + application_name: shipping + application_port: 7009 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: kubernetes_cluster + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-shipping:v8 + + ################################################### + # + # Cart + # + ################################################### + + cart_component: + type: cart.component~service.application#docker.image::kubernetes@kubernetes.cluster + properties: + application_name: cart + application_port: 7070 + application_protocol: grpc + disable_profiler: '1' + mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} + mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} + mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} + mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} + mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} + mysql_table: 'cart' + mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} + + requirements: + - database: cart_database + - host: kubernetes_cluster + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-cart:v8 + + cart_database: + type: mysql.database~mysql.database::ansible@mysql.dbms->kubernetes.cluster + properties: + database_name: cart + database_user: cart + database_password: {get_input: database_password} + requirements: + - host: cart_dbms + + cart_dbms: + type: mysql.dbms~mysql.dbms#dbms.image::kubernetes@kubernetes.cluster + properties: + dbms_name: unfurl-technology-boutique-cart-dbms + dbms_password: {get_input: dbms_password} + requirements: + - host: kubernetes_cluster + artifacts: + dbms_image: + type: dbms.image + file: 5.7 + + ################################################### + # + # Product + # + ################################################### + + product_component: + type: product.component~service.application#docker.image::kubernetes@kubernetes.cluster + properties: + application_name: product + application_port: 7007 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: kubernetes_cluster + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-product:v8 + + ################################################### + # + # Recommendation + # + ################################################### + + recommendation_component: + type: recommendation.component~service.application#docker.image::kubernetes@kubernetes.cluster + properties: + application_name: recommendation + application_port: 7008 + application_protocol: grpc + disable_profiler: '1' + PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} + requirements: + - product: product_component + - host: kubernetes_cluster + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-recommendation:v8 + + ################################################### + # + # Advertisement + # + ################################################### + + advertisement_component: + type: advertisement.component~service.application#docker.image::kubernetes@kubernetes.cluster + properties: + application_name: advertisement + application_port: 7000 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: kubernetes_cluster + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-advertisement:v8 + + ################################################### + # + # Analytical + # + ################################################### + + analytics_component: + type: analytics.component~service.application#docker.image::kubernetes@kubernetes.cluster + properties: + application_name: analytics + application_port: 7001 + application_protocol: grpc + CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} + RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} + optional_analytical_feature: 'false' + premium_analytical_feature: 'false' + requirements: + - checkout: checkout_component + - recommendation: recommendation_component + - host: kubernetes_cluster + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-analytics:v8 + + ################################################### + # + # Kubernetes + # + ################################################### + + kubernetes_cluster: + type: kubernetes.cluster + properties: + k8s_host: {get_input: k8s_host} + k8s_ca_cert_file: {get_input: k8s_ca_cert_file} + k8s_client_cert_file: {get_input: k8s_client_cert_file} + k8s_client_key_file: {get_input: k8s_client_key_file} + requirements: + - host: kubernetes_provider + + kubernetes_provider: + type: cloud.provider diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/inputs.yaml new file mode 100644 index 0000000000..efdff7c51b --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/inputs.yaml @@ -0,0 +1 @@ +env: KUBERNETES diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/expected.yaml new file mode 100644 index 0000000000..e96254d028 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/expected.yaml @@ -0,0 +1,402 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + + dbms_password: + type: string + + os_network: + type: string + + os_ssh_key_name: + type: string + + os_ssh_user: + type: string + + os_ssh_key_file: + type: string + + os_region_name: + type: string + + os_auth_type: + type: string + + os_auth_url: + type: string + + os_identity_api_version: + type: string + + os_interface: + type: string + + os_application_credential_id: + type: string + + os_application_credential_secret: + type: string + + node_templates: + ################################################### + # + # Frontend + # + ################################################### + + frontend_component: + type: frontend.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: frontend + application_port: 8080 + application_protocol: http + disable_profiler: '1' + CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} + CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} + SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} + CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} + PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} + RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} + AD_SERVICE_ADDR: {eval: '.::.requirements::[.name=advertisement]::.target::application_endpoint'} + optional_payment_feature: 'false' + premium_payment_feature: 'false' + SHOPPING_ASSISTANT_SERVICE_ADDR: 'required-but-not-used' + requirements: + - checkout: checkout_component + - currency: currency_component + - shipping: shipping_component + - cart: cart_component + - product: product_component + - recommendation: recommendation_component + - advertisement: advertisement_component + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-frontend:v8 + + frontend_ingress: + type: ingress~ingress::ansible@remote.machine + requirements: + - application: frontend_component + - host: virtual_machine + + ################################################### + # + # Checkout + # + ################################################### + + checkout_component: + type: checkout.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: checkout + application_port: 7003 + application_protocol: grpc + disable_profiler: '1' + PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} + SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} + PAYMENT_SERVICE_ADDR: {eval: '.::.requirements::[.name=payment]::.target::application_endpoint'} + EMAIL_SERVICE_ADDR: {eval: '.::.requirements::[.name=email]::.target::application_endpoint'} + CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} + CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} + optional_payment_feature: 'false' + premium_payment_feature: 'false' + requirements: + - email: email_component + - payment: payment_component + - currency: currency_component + - shipping: shipping_component + - cart: cart_component + - product: product_component + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-checkout:v8 + + ################################################### + # + # Email + # + ################################################### + + email_component: + type: email.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: email + application_port: 7005 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-email:v8 + + ################################################### + # + # Payment + # + ################################################### + + payment_component: + type: payment.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: payment + application_port: 7006 + application_protocol: grpc + disable_profiler: '1' + optional_payment_feature: 'false' + premium_payment_feature: 'false' + requirements: + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-payment:v8 + + ################################################### + # + # Currency + # + ################################################### + + currency_component: + type: currency.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: currency + application_port: 7004 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-currency:v8 + + ################################################### + # + # Shipping + # + ################################################### + + shipping_component: + type: shipping.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: shipping + application_port: 7009 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-shipping:v8 + + ################################################### + # + # Cart + # + ################################################### + + cart_component: + type: cart.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: cart + application_port: 7070 + application_protocol: grpc + disable_profiler: '1' + mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} + mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} + mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} + mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} + mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} + mysql_table: 'cart' + mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} + requirements: + - database: cart_database + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-cart:v8 + + cart_database: + type: mysql.database~mysql.database::ansible@mysql.dbms->docker.engine->remote.machine + properties: + database_name: cart + database_user: cart + database_password: {get_input: database_password} + requirements: + - host: cart_dbms + + cart_dbms: + type: mysql.dbms~mysql.dbms#dbms.image::compose@docker.engine->remote.machine + properties: + dbms_name: unfurl-technology-boutique-cart-dbms + dbms_password: {get_input: dbms_password} + requirements: + - host: docker_engine + artifacts: + dbms_image: + type: dbms.image + file: 5.7 + + ################################################### + # + # Product + # + ################################################### + + product_component: + type: product.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: product + application_port: 7007 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-product:v8 + + ################################################### + # + # Recommendation + # + ################################################### + + recommendation_component: + type: recommendation.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: recommendation + application_port: 7008 + application_protocol: grpc + disable_profiler: '1' + PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} + requirements: + - product: product_component + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-recommendation:v8 + + ################################################### + # + # Advertisement + # + ################################################### + + advertisement_component: + type: advertisement.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: advertisement + application_port: 7000 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-advertisement:v8 + + ################################################### + # + # Virtual Machine + # + ################################################### + + docker_engine: + type: docker.engine~docker.engine::ansible@remote.machine + requirements: + - host: virtual_machine + + node_agent: + type: node.agent~service.application#tar.archive::ansible@*->remote.machine + properties: + application_name: node_exporter + application_port: 9100 + application_protocol: http + requirements: + - host: virtual_machine + artifacts: + tar_archive: + type: tar.archive + file: https://github.com/prometheus/node_exporter/releases/download/v1.6.0/node_exporter-1.6.0.linux-amd64.tar.gz + properties: + extra_opts: + - '--strip-components=1' + + promtail_agent: + type: promtail.agent~software.application#apt.package::ansible@*->remote.machine + properties: + application_name: promtail + requirements: + - host: virtual_machine + artifacts: + apt_package: + type: apt.package + file: promtail + properties: + repository: grafana + key: https://apt.grafana.com/gpg.key + source: https://apt.grafana.com stable main + + falco_agent: + type: falco.agent~software.application#apt.package::ansible@*->remote.machine + properties: + application_name: falco + requirements: + - host: virtual_machine + artifacts: + apt_package: + type: apt.package + file: falco + properties: + repository: falco + key: https://falco.org/repo/falcosecurity-packages.asc + source: https://download.falco.org/packages/deb stable main + env: FALCO_FRONTEND=noninteractive + + virtual_machine: + type: virtual.machine~virtual.machine#machine.image::terraform@openstack.provider + properties: + machine_name: unfurl-technology-boutique + ports: ['80', '2375', '9100'] + flavor: m1.large + network: {get_input: os_network} + ssh_key_name: {get_input: os_ssh_key_name} + ssh_user: {get_input: os_ssh_user} + ssh_key_file: {get_input: os_ssh_key_file} + requirements: + - host: openstack_provider + artifacts: + machine_image: + type: machine.image + file: Ubuntu 22.04 + + openstack_provider: + type: openstack.provider + properties: + os_region_name: {get_input: os_region_name} + os_auth_type: {get_input: os_auth_type} + os_auth_url: {get_input: os_auth_url} + os_identity_api_version: {get_input: os_identity_api_version} + os_interface: {get_input: os_interface} + os_application_credential_id: {get_input: os_application_credential_id} + os_application_credential_secret: {get_input: os_application_credential_secret} diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/inputs.yaml new file mode 100644 index 0000000000..788bbd80c0 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/inputs.yaml @@ -0,0 +1,2 @@ +env: OPENSTACK +tier: LARGE diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/test.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/test.yaml new file mode 100644 index 0000000000..616f52519b --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/test.yaml @@ -0,0 +1,21 @@ +merge: + topology_template: + node_templates: + analytics_component: + type: analytics.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: analytics + application_port: 7001 + application_protocol: grpc + CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} + RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} + optional_analytical_feature: 'false' + premium_analytical_feature: 'false' + requirements: + - checkout: checkout_component + - recommendation: recommendation_component + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-analytics:v8 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/expected.yaml new file mode 100644 index 0000000000..f92e8eed41 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/expected.yaml @@ -0,0 +1,402 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + + dbms_password: + type: string + + os_network: + type: string + + os_ssh_key_name: + type: string + + os_ssh_user: + type: string + + os_ssh_key_file: + type: string + + os_region_name: + type: string + + os_auth_type: + type: string + + os_auth_url: + type: string + + os_identity_api_version: + type: string + + os_interface: + type: string + + os_application_credential_id: + type: string + + os_application_credential_secret: + type: string + + node_templates: + ################################################### + # + # Frontend + # + ################################################### + + frontend_component: + type: frontend.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: frontend + application_port: 8080 + application_protocol: http + disable_profiler: '1' + CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} + CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} + SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} + CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} + PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} + RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} + AD_SERVICE_ADDR: {eval: '.::.requirements::[.name=advertisement]::.target::application_endpoint'} + optional_payment_feature: 'false' + premium_payment_feature: 'false' + SHOPPING_ASSISTANT_SERVICE_ADDR: 'required-but-not-used' + requirements: + - checkout: checkout_component + - currency: currency_component + - shipping: shipping_component + - cart: cart_component + - product: product_component + - recommendation: recommendation_component + - advertisement: advertisement_component + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-frontend:v8 + + frontend_ingress: + type: ingress~ingress::ansible@remote.machine + requirements: + - application: frontend_component + - host: virtual_machine + + ################################################### + # + # Checkout + # + ################################################### + + checkout_component: + type: checkout.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: checkout + application_port: 7003 + application_protocol: grpc + disable_profiler: '1' + PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} + SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} + PAYMENT_SERVICE_ADDR: {eval: '.::.requirements::[.name=payment]::.target::application_endpoint'} + EMAIL_SERVICE_ADDR: {eval: '.::.requirements::[.name=email]::.target::application_endpoint'} + CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} + CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} + optional_payment_feature: 'false' + premium_payment_feature: 'false' + requirements: + - email: email_component + - payment: payment_component + - currency: currency_component + - shipping: shipping_component + - cart: cart_component + - product: product_component + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-checkout:v8 + + ################################################### + # + # Email + # + ################################################### + + email_component: + type: email.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: email + application_port: 7005 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-email:v8 + + ################################################### + # + # Payment + # + ################################################### + + payment_component: + type: payment.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: payment + application_port: 7006 + application_protocol: grpc + disable_profiler: '1' + optional_payment_feature: 'false' + premium_payment_feature: 'false' + requirements: + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-payment:v8 + + ################################################### + # + # Currency + # + ################################################### + + currency_component: + type: currency.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: currency + application_port: 7004 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-currency:v8 + + ################################################### + # + # Shipping + # + ################################################### + + shipping_component: + type: shipping.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: shipping + application_port: 7009 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-shipping:v8 + + ################################################### + # + # Cart + # + ################################################### + + cart_component: + type: cart.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: cart + application_port: 7070 + application_protocol: grpc + disable_profiler: '1' + mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} + mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} + mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} + mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} + mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} + mysql_table: 'cart' + mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} + requirements: + - database: cart_database + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-cart:v8 + + cart_database: + type: mysql.database~mysql.database::ansible@mysql.dbms->docker.engine->remote.machine + properties: + database_name: cart + database_user: cart + database_password: {get_input: database_password} + requirements: + - host: cart_dbms + + cart_dbms: + type: mysql.dbms~mysql.dbms#dbms.image::compose@docker.engine->remote.machine + properties: + dbms_name: unfurl-technology-boutique-cart-dbms + dbms_password: {get_input: dbms_password} + requirements: + - host: docker_engine + artifacts: + dbms_image: + type: dbms.image + file: 5.7 + + ################################################### + # + # Product + # + ################################################### + + product_component: + type: product.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: product + application_port: 7007 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-product:v8 + + ################################################### + # + # Recommendation + # + ################################################### + + recommendation_component: + type: recommendation.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: recommendation + application_port: 7008 + application_protocol: grpc + disable_profiler: '1' + PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} + requirements: + - product: product_component + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-recommendation:v8 + + ################################################### + # + # Advertisement + # + ################################################### + + advertisement_component: + type: advertisement.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: advertisement + application_port: 7000 + application_protocol: grpc + disable_profiler: '1' + requirements: + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-advertisement:v8 + + ################################################### + # + # Virtual Machine + # + ################################################### + + docker_engine: + type: docker.engine~docker.engine::ansible@remote.machine + requirements: + - host: virtual_machine + + node_agent: + type: node.agent~service.application#tar.archive::ansible@*->remote.machine + properties: + application_name: node_exporter + application_port: 9100 + application_protocol: http + requirements: + - host: virtual_machine + artifacts: + tar_archive: + type: tar.archive + file: https://github.com/prometheus/node_exporter/releases/download/v1.6.0/node_exporter-1.6.0.linux-amd64.tar.gz + properties: + extra_opts: + - '--strip-components=1' + + promtail_agent: + type: promtail.agent~software.application#apt.package::ansible@*->remote.machine + properties: + application_name: promtail + requirements: + - host: virtual_machine + artifacts: + apt_package: + type: apt.package + file: promtail + properties: + repository: grafana + key: https://apt.grafana.com/gpg.key + source: https://apt.grafana.com stable main + + falco_agent: + type: falco.agent~software.application#apt.package::ansible@*->remote.machine + properties: + application_name: falco + requirements: + - host: virtual_machine + artifacts: + apt_package: + type: apt.package + file: falco + properties: + repository: falco + key: https://falco.org/repo/falcosecurity-packages.asc + source: https://download.falco.org/packages/deb stable main + env: FALCO_FRONTEND=noninteractive + + virtual_machine: + type: virtual.machine~virtual.machine#machine.image::terraform@openstack.provider + properties: + machine_name: unfurl-technology-boutique + ports: ['80', '2375', '9100'] + flavor: m1.medium + network: {get_input: os_network} + ssh_key_name: {get_input: os_ssh_key_name} + ssh_user: {get_input: os_ssh_user} + ssh_key_file: {get_input: os_ssh_key_file} + requirements: + - host: openstack_provider + artifacts: + machine_image: + type: machine.image + file: Ubuntu 22.04 + + openstack_provider: + type: openstack.provider + properties: + os_region_name: {get_input: os_region_name} + os_auth_type: {get_input: os_auth_type} + os_auth_url: {get_input: os_auth_url} + os_identity_api_version: {get_input: os_identity_api_version} + os_interface: {get_input: os_interface} + os_application_credential_id: {get_input: os_application_credential_id} + os_application_credential_secret: {get_input: os_application_credential_secret} diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/inputs.yaml new file mode 100644 index 0000000000..3070bec9b6 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/inputs.yaml @@ -0,0 +1,2 @@ +env: OPENSTACK +tier: MEDIUM diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/test.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/test.yaml new file mode 100644 index 0000000000..616f52519b --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/test.yaml @@ -0,0 +1,21 @@ +merge: + topology_template: + node_templates: + analytics_component: + type: analytics.component~service.application#docker.image::compose@docker.engine->remote.machine + properties: + application_name: analytics + application_port: 7001 + application_protocol: grpc + CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} + RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} + optional_analytical_feature: 'false' + premium_analytical_feature: 'false' + requirements: + - checkout: checkout_component + - recommendation: recommendation_component + - host: docker_engine + artifacts: + docker_image: + type: docker.image + file: milesstoetzner/boutique-analytics:v8 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml new file mode 100644 index 0000000000..24afc30629 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml @@ -0,0 +1,852 @@ +tosca_definitions_version: tosca_variability_1_0_rc_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + retailer_name: + type: string + + global_service_gateway_endpoint: + type: string + + global_service_gateway_token: + type: string + + payment_provider_endpoint: + type: string + + payment_provider_token: + type: string + + coffee_provider_type: + type: string + conditions: {logic_expression: has_coffee} + + coffee_provider_endpoint: + type: string + conditions: {logic_expression: has_coffee} + + coffee_provider_token: + type: string + conditions: {logic_expression: has_coffee} + + os_network: + type: string + + os_ssh_key_name: + type: string + + os_ssh_user: + type: string + + os_ssh_key_file: + type: string + + os_region_name: + type: string + + os_auth_type: + type: string + + os_auth_url: + type: string + + os_identity_api_version: + type: string + + os_interface: + type: string + + os_application_credential_id: + type: string + + os_application_credential_secret: + type: string + + gcp_region: + type: string + + gcp_service_account_file: + type: string + + gcp_project: + type: string + + k8s_host: + type: string + + k8s_ca_cert_file: + type: string + + k8s_client_cert_file: + type: string + + k8s_client_key_file: + type: string + + variability: + expressions: + has_info_logging: {equal: [{variability_input: ERROR}, true]} + has_debug_logging: {equal: [{variability_input: DEBUG}, true]} + has_error_masking: {equal: [{variability_input: errors}, true]} + + has_coffee: {equal: [{variability_input: coffee}, true]} + + has_introspection: {equal: [{variability_input: introspection}, true]} + has_playground: {equal: [{variability_input: playground}, true]} + + has_import: {equal: [{variability_input: import}, true]} + has_import_schema_a: {equal: [{variability_input: import_schema_a}, A]} + has_import_schema_b: {equal: [{variability_input: import_schema_b}, B]} + + has_payment_merchant_a: {equal: [{variability_input: payment_merchant_a}, true]} + has_payment_merchant_b: {equal: [{variability_input: payment_merchant_b}, true]} + + is_gcp: {equal: [{variability_input: env}, GCP]} + is_local: {equal: [{variability_input: env}, LOCAL]} + is_customer: {equal: [{variability_input: env}, CUSTOMER]} + is_openstack: {equal: [{variability_input: env}, OPENSTACK]} + inputs: + env: + type: string + default: OPENSTACK + + errors: + type: boolean + + logging: + type: string + + coffee: + type: boolean + + introspection: + type: boolean + + playground: + type: boolean + + import: + type: boolean + + import_schema: + type: string + + payment_merchant_a: + type: boolean + + payment_merchant_b: + type: boolean + + node_templates: + ################################################### + # + # Retailer Dashboard + # + ################################################### + + retailer_frontend_dashboard: + type: retailer.frontend.dashboard + properties: + - application_name: retailer-frontend-dashboard + - application_port: 3000 + - application_protocol: http + - logging_level: + value: info + conditions: {logic_expression: has_info_logging} + + - logging_level: + value: info + conditions: {logic_expression: has_debug_logging} + + - retailer_service_gateway_endpoint: {eval: '.::.requirements::[.name=retailer_service_gateway]::.target::application_endpoint'} + requirements: + - retailer_service_gateway: retailer_service_gateway + - host: local_docker_engine + - host: remote_docker_engine + - host: kubernetes_cluster + artifacts: + - docker_image: + type: docker.image + file: retailer.frontend.dashboard:vX.Y.Z + + ################################################### + # + # Retailer Terminal + # + ################################################### + + retailer_frontend_terminal: + type: retailer.frontend.terminal + properties: + - application_name: retailer-frontend-terminal + - application_port: 3000 + - application_protocol: http + - logging_level: + value: info + conditions: {logic_expression: has_info_logging} + + - logging_level: + value: info + conditions: {logic_expression: has_debug_logging} + + - retailer_service_gateway_endpoint: {eval: '.::.requirements::[.name=retailer_service_gateway]::.target::application_endpoint'} + requirements: + - retailer_service_gateway: retailer_service_gateway + - host: local_docker_engine + - host: remote_docker_engine + - host: kubernetes_cluster + artifacts: + - docker_image: + type: docker.image + file: retailer.frontend.dashboard:vX.Y.Z + + ################################################### + # + # Retailer Gateway + # + ################################################### + + retailer_service_gateway: + type: retailer.service.gateway + persistent: true + properties: + - application_name: retailer-service-gateway + - application_port: 4000 + - application_protocol: graphql + + - logging_level: + value: info + conditions: {logic_expression: has_info_logging} + + - logging_level: + value: info + conditions: {logic_expression: has_debug_logging} + + - retailer_name: {get_input: retailer_name} + + - graphql_introspection: + value: true + conditions: {logic_expression: has_introspection} + + - graphql_introspection: + value: false + conditions: {not: {logic_expression: has_introspection}} + + - graphql_playground: + value: true + conditions: {logic_expression: has_playground} + + - graphql_playground: + value: false + conditions: {not: {logic_expression: has_playground}} + + - has_error_masking: + value: true + conditions: {logic_expression: has_errors} + + - has_error_masking: + value: false + conditions: {not: {logic_expression: has_errors}} + + - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} + - retailer_service_core_endpoint: {eval: '.::.requirements::[.name=retailer_service_core]::.target::application_endpoint'} + - retailer_service_jobs_endpoint: {eval: '.::.requirements::[.name=retailer_service_jobs]::.target::application_endpoint'} + - retailer_service_stores_endpoint: {eval: '.::.requirements::[.name=retailer_service_stores]::.target::application_endpoint'} + - retailer_service_products_endpoint: {eval: '.::.requirements::[.name=retailer_service_products]::.target::application_endpoint'} + - retailer_service_stocks_endpoint: {eval: '.::.requirements::[.name=retailer_service_stocks]::.target::application_endpoint'} + - retailer_service_orders_endpoint: {eval: '.::.requirements::[.name=retailer_service_orders]::.target::application_endpoint'} + - retailer_service_global_endpoint: {eval: '.::.requirements::[.name=retailer_service_global]::.target::application_endpoint'} + requirements: + - retailer_service_core: retailer_service_core + - retailer_service_jobs: retailer_service_jobs + - retailer_service_stores: retailer_service_stores + - retailer_service_products: retailer_service_products + - retailer_service_stocks: retailer_service_stocks + - retailer_service_orders: retailer_service_orders + - retailer_service_global: retailer_service_global + - host: local_docker_engine + - host: remote_docker_engine + - host: kubernetes_cluster + artifacts: + - docker_image: + type: docker.image + file: retailer.service.gateway:vX.Y.Z + + retailer_gateway_ingress: + type: ingress + requirements: + - application: retailer_service_gateway + - host: virtual_machine + - host: kubernetes_cluster + + ################################################### + # + # Retailer Core + # + ################################################### + + retailer_service_core: + type: retailer.service.core + properties: + - application_name: retailer-service-core + - application_port: 4000 + - application_protocol: graphql + - logging_level: + value: info + conditions: {logic_expression: has_info_logging} + + - logging_level: + value: info + conditions: {logic_expression: has_debug_logging} + + - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} + + - coffee_enabled: + value: true + conditions: {logic_expression: has_coffee} + + - coffee_enabled: + value: false + conditions: {not: {logic_expression: has_coffee}} + + - coffee_provider_type: + value: {get_input: coffee_provider_type} + conditions: {logic_expression: has_coffee} + + - coffee_provider_endpoint: + value: {get_input: coffee_provider_endpoint} + conditions: {logic_expression: has_coffee} + + - coffee_provider_token: + value: {get_input: coffee_provider_token} + conditions: {logic_expression: has_coffee} + + - payment_provider_endpoint: {get_input: payment_provider_endpoint} + - payment_provider_token: {get_input: payment_provider_token} + + - payment_merchant_a_enabled: + value: true + conditions: {logic_expression: has_payment_merchant_a} + + - payment_merchant_a_enabled: + value: false + conditions: {not: {logic_expression: has_payment_merchant_a}} + + - payment_merchant_b_enabled: + value: true + conditions: {logic_expression: has_payment_merchant_b} + + - payment_merchant_b_enabled: + value: false + conditions: {not: {logic_expression: has_payment_merchant_b}} + + requirements: + - host: local_docker_engine + - host: remote_docker_engine + - host: kubernetes_cluster + artifacts: + - docker_image: + type: docker.image + file: retailer.service.core:vX.Y.Z + + ################################################### + # + # Retailer Jobs + # + ################################################### + + retailer_service_jobs: + type: retailer.service.jobs + properties: + - application_name: retailer-service-core + - application_port: 4000 + - application_protocol: graphql + - logging_level: + value: info + conditions: {logic_expression: has_info_logging} + + - logging_level: + value: info + conditions: {logic_expression: has_debug_logging} + + - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} + + requirements: + - host: local_docker_engine + - host: remote_docker_engine + - host: kubernetes_cluster + artifacts: + - docker_image: + type: docker.image + file: retailer.service.jobs:vX.Y.Z + + ################################################### + # + # Retailer Stores + # + ################################################### + + retailer_service_stores: + type: retailer.service.stores + properties: + - application_name: retailer-service-stores + - application_port: 4000 + - application_protocol: graphql + - logging_level: + value: info + conditions: {logic_expression: has_info_logging} + + - logging_level: + value: info + conditions: {logic_expression: has_debug_logging} + + - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} + + - mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} + - mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} + - mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} + - mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} + - mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} + - mysql_table: 'stores' + - mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} + + - bucket_name: {eval: '.::.requirements::[.name=bucket]::.target::bucket_name'} + - bucket_endpoint: {eval: '.::.requirements::[.name=bucket]::.target::bucket_endpoint'} + - bucket_token: {eval: '.::.requirements::[.name=bucket]::.target::bucket_token'} + - bucket_dialect: {eval: '.::.requirements::[.name=bucket]::.target::bucket_dialect'} + + requirements: + - database: retailer_database_stores + - bucket: retailer_bucket_stores + - host: local_docker_engine + - host: remote_docker_engine + - host: kubernetes_cluster + artifacts: + - docker_image: + type: docker.image + file: retailer.service.stores:vX.Y.Z + + retailer_database_stores: + type: mysql.database + properties: + - database_name: stores + - database_user: stores + - database_password: {get_input: database_password} + requirements: + - host: retailer_dbms + + # TODO: needs implementations + retailer_bucket_stores: + type: bucket + properties: + - bucket_name: stores + - bucket_dialect: + value: minio + conditions: {node_presence: minio} + + - bucket_dialect: + value: gcp + conditions: {node_presence: gcp_cloudstorage} + requirements: + - host: retailer_minio + - host: gcp_cloudstorage + + ################################################### + # + # Retailer Products + # + ################################################### + + retailer_service_products: + type: retailer.service.products + properties: + - application_name: retailer-service-products + - application_port: 4000 + - application_protocol: graphql + - logging_level: + value: info + conditions: {logic_expression: has_info_logging} + + - logging_level: + value: info + conditions: {logic_expression: has_debug_logging} + + - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} + + - import_enabled: + value: true + conditions: {logic_expression: has_import} + + - import_enabled: + value: false + conditions: {not: {logic_expression: has_import}} + + - import_schema: + value: a + conditions: {logic_expression: has_import_schema_a} + + - import_schema: + value: b + conditions: {logic_expression: has_import_schema_b} + + - mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} + - mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} + - mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} + - mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} + - mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} + - mysql_table: 'stores' + - mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} + + - bucket_name: {eval: '.::.requirements::[.name=bucket]::.target::bucket_name'} + - bucket_endpoint: {eval: '.::.requirements::[.name=bucket]::.target::bucket_endpoint'} + - bucket_token: {eval: '.::.requirements::[.name=bucket]::.target::bucket_token'} + - bucket_dialect: {eval: '.::.requirements::[.name=bucket]::.target::bucket_dialect'} + + requirements: + - database: retailer_database_products + - bucket: retailer_bucket_products + - host: local_docker_engine + - host: remote_docker_engine + - host: kubernetes_cluster + artifacts: + - docker_image: + type: docker.image + file: retailer.service.products:vX.Y.Z + + retailer_database_products: + type: mysql.database + properties: + - database_name: products + - database_user: products + - database_password: {get_input: database_password} + requirements: + - host: retailer_dbms + + retailer_bucket_products: + type: bucket + properties: + - bucket_name: products + - bucket_dialect: + value: minio + conditions: {node_presence: minio} + + - bucket_dialect: + value: gcp + conditions: {node_presence: gcp_cloudstorage} + requirements: + - host: retailer_minio + - host: gcp_cloudstorage + + ################################################### + # + # Retailer Stocks + # + ################################################### + + retailer_service_stocks: + type: retailer.service.stocks + properties: + - application_name: retailer-service-stocks + - application_port: 4000 + - application_protocol: graphql + - logging_level: + value: info + conditions: {logic_expression: has_info_logging} + + - logging_level: + value: info + conditions: {logic_expression: has_debug_logging} + + - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} + + - mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} + - mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} + - mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} + - mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} + - mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} + - mysql_table: 'stores' + - mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} + requirements: + - database: retailer_database_stocks + - host: local_docker_engine + - host: remote_docker_engine + - host: kubernetes_cluster + artifacts: + - docker_image: + type: docker.image + file: retailer.service.stocks:vX.Y.Z + + retailer_database_stocks: + type: mysql.database + properties: + - database_name: stocks + - database_user: stocks + - database_password: {get_input: database_password} + requirements: + - host: retailer_dbms + + ################################################### + # + # Retailer Orders + # + ################################################### + + retailer_service_orders: + type: retailer.service.orders + properties: + - application_name: retailer-service-orders + - application_port: 4000 + - application_protocol: graphql + - logging_level: + value: info + conditions: {logic_expression: has_info_logging} + + - logging_level: + value: info + conditions: {logic_expression: has_debug_logging} + + - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} + + - mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} + - mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} + - mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} + - mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} + - mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} + - mysql_table: 'stores' + - mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} + requirements: + - database: retailer_database_orders + - host: local_docker_engine + - host: remote_docker_engine + - host: kubernetes_cluster + artifacts: + - docker_image: + type: docker.image + file: retailer.service.stocks:vX.Y.Z + + retailer_database_orders: + type: mysql.database + properties: + - database_name: orders + - database_user: orders + - database_password: {get_input: database_password} + requirements: + - host: retailer_dbms + + ################################################### + # + # Retailer Global + # + ################################################### + + retailer_service_global: + type: retailer.service.global + properties: + - application_name: retailer-service-global + - application_port: 4000 + - application_protocol: graphql + - logging_level: + value: info + conditions: {logic_expression: has_info_logging} + + - logging_level: + value: info + conditions: {logic_expression: has_debug_logging} + + - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} + + - global_service_gateway_endpoint: {get_input: global_service_gateway_endpoint} + - global_service_gateway_token: {get_input: global_service_gateway_token} + requirements: + - database: retailer_database_orders + - host: local_docker_engine + - host: remote_docker_engine + - host: kubernetes_cluster + artifacts: + - docker_image: + type: docker.image + file: retailer.service.stocks:vX.Y.Z + + ################################################### + # + # Retailer DBMS + # + ################################################### + + retailer_dbms: + type: mysql.dbms + properties: + - dbms_name: unfurl-technology-industry-dbms + - dbms_password: {get_input: dbms_password} + requirements: + - host: local_docker_engine + - host: remote_docker_engine + - host: kubernetes_cluster + artifacts: + - dbms_image: + type: dbms.image + file: 5.7 + + ################################################### + # + # Retailer Cache + # + ################################################### + + retailer_cache_redis: + type: redis.server + properties: + - application_name: retailer-cache-redis + - application_port: 6379 + - application_protocol: redis + requirements: + - host: local_docker_engine + - host: remote_docker_engine + - host: kubernetes_cluster + artifacts: + - docker_image: + type: docker.image + file: redis:7.4.0 + + ################################################### + # + # Retailer MinIO + # + ################################################### + + retailer_minio: + type: minio.server + properties: + - application_name: retailer-minio-server + - application_port: 9000 + - application_protocol: http + requirements: + - host: local_docker_engine + - host: remote_docker_engine + - host: + node: kubernetes_cluster + conditions: {logic_expression: is_customer} + artifacts: + - docker_image: + type: docker.image + file: minio/minio:RELEASE.2024-08-29T01-40-52Z + + ################################################### + # + # Local Machine + # + ################################################### + + # TODO: handle local docker engine: we do not deploy the docker engine, but assumed its already installed. we might ping it to verify it! + # TODO: handle applications hosted on local docker engine + local_docker_engine: + type: docker.engine + requirements: + - host: local_machine + + local_machine: + type: local.machine + + ################################################### + # + # Virtual Machine + # + ################################################### + + remote_docker_engine: + type: docker.engine + requirements: + - host: virtual_machine + + virtual_machine: + type: virtual.machine + properties: + - machine_name: unfurl-technology-boutique + - ports: ['80', '2375', '9100'] + - flavor: + value: m1.medium + conditions: {equal: [{variability_input: tier}, MEDIUM]} + - flavor: + value: m1.large + conditions: {equal: [{variability_input: tier}, LARGE]} + - network: {get_input: os_network} + - ssh_user: {get_input: os_ssh_user} + - ssh_key_name: {get_input: os_ssh_key_name} + - ssh_key_file: {get_input: os_ssh_key_file} + requirements: + - host: openstack_provider + artifacts: + - machine_image: + type: machine.image + file: Ubuntu 22.04 + + openstack_provider: + type: openstack.provider + conditions: {logic_expression: is_openstack} + properties: + - os_region_name: {get_input: os_region_name} + - os_auth_type: {get_input: os_auth_type} + - os_auth_url: {get_input: os_auth_url} + - os_identity_api_version: {get_input: os_identity_api_version} + - os_interface: {get_input: os_interface} + - os_application_credential_id: {get_input: os_application_credential_id} + - os_application_credential_secret: {get_input: os_application_credential_secret} + + ################################################### + # + # GCP + # + ################################################### + + gcp_kubernetesengine: + type: gcp.kubernetesengine + requirements: + - host: gcp_provider + + gcp_cloudstorage: + type: gcp.cloudstorage + requirements: + - host: gcp_provider + + gcp_cloudrun: + type: gcp.cloudrun + requirements: + - host: gcp_provider + + gcp_cloudsql: + type: gcp.cloudsql + requirements: + - host: gcp_provider + + gcp_provider: + type: gcp.provider + conditions: {logic_expression: is_gcp} + properties: + - gcp_region: {get_input: gcp_region} + - gcp_service_account_file: {get_input: gcp_service_account_file} + - gcp_project: {get_input: gcp_project} + + ################################################### + # + # Kubernetes + # + ################################################### + + # TODO: credentials are only present at customer else they are dynamic! + kubernetes_cluster: + type: kubernetes.cluster + properties: + - k8s_host: {get_input: k8s_host} + - k8s_ca_cert_file: {get_input: k8s_ca_cert_file} + - k8s_client_cert_file: {get_input: k8s_client_cert_file} + - k8s_client_key_file: {get_input: k8s_client_key_file} + requirements: + - host: kubernetes_provider + - host: gcp_kubernetesengine + + kubernetes_provider: + type: cloud.provider + conditions: {logic_expression: is_customer} diff --git a/src/normative/types/core/nodes.ts b/src/normative/types/core/nodes.ts index 87ab3080c6..fe65ba56d0 100644 --- a/src/normative/types/core/nodes.ts +++ b/src/normative/types/core/nodes.ts @@ -195,6 +195,14 @@ const nodes: NodeTypeMap = { ...MetadataNormative(), ...MetadataAbstract(), }, + requirements: [ + { + host: { + capability: 'tosca.capabilities.Compute', + relationship: 'tosca.relationships.HostedOn', + }, + }, + ], }, 'relational.database': { derived_from: 'database', @@ -217,6 +225,51 @@ const nodes: NodeTypeMap = { ...MetadataAbstract(), }, }, + cache: { + derived_from: 'software.application', + }, + storage: { + derived_from: 'node', + }, + 'block.storage': { + derived_from: 'storage', + }, + 'object.storage': { + derived_from: 'storage', + }, + 'file.storage': { + derived_from: 'storage', + }, + bucket: { + derived_from: 'object.storage', + metadata: { + ...MetadataNormative(), + }, + properties: { + bucket_name: { + type: 'string', + }, + bucket_dialect: { + type: 'string', + }, + }, + attributes: { + bucket_endpoint: { + type: 'string', + }, + bucket_token: { + type: 'string', + }, + }, + requirements: [ + { + host: { + capability: 'tosca.capabilities.Compute', + relationship: 'tosca.relationships.HostedOn', + }, + }, + ], + }, ingress: { derived_from: 'node', metadata: { diff --git a/src/normative/types/extended/nodes.ts b/src/normative/types/extended/nodes.ts index f41f2e9338..267ea7ff87 100644 --- a/src/normative/types/extended/nodes.ts +++ b/src/normative/types/extended/nodes.ts @@ -55,6 +55,20 @@ const nodes: NodeTypeMap = { }, }, }, + 'reactjs.service.application': { + derived_from: 'service.application', + metadata: { + ...MetadataNormative(), + ...MetadataAbstract(), + }, + properties: { + // TODO: which language?! + application_language: { + type: 'string', + default: 'nodejs18', + }, + }, + }, 'python.runtime': { derived_from: 'software.runtime', metadata: { @@ -337,6 +351,30 @@ const nodes: NodeTypeMap = { }, }, }, + 'gcp.kubernetesengine': { + derived_from: 'gcp.service', + metadata: { + ...MetadataNormative(), + }, + properties: { + gcp_service: { + type: 'string', + default: 'container.googleapis.com', + }, + }, + }, + 'gcp.cloudstorage': { + derived_from: 'gcp.service', + metadata: { + ...MetadataNormative(), + }, + properties: { + gcp_service: { + type: 'string', + default: 'storage.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', @@ -530,6 +568,12 @@ const nodes: NodeTypeMap = { }, ], }, + 'minio.server': { + derived_from: 'software.application', + }, + 'redis.server': { + derived_from: 'cache', + }, } export default nodes From 07a86f24f67241ae0662e5f8ac0fe3310eacd37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Fri, 6 Sep 2024 16:15:09 +0200 Subject: [PATCH 02/18] continue --- docs/docs/variability4tosca/rules/index.md | 700 +- .../rules/technology-rules.yaml | 201 + .../lib/retailer.yaml | 31229 ++++++++++++++++ .../lib/rules.yaml | 201 + .../lib/tosca-vintner-profile-core.yaml | 2158 +- .../lib/tosca-vintner-profile-extended.yaml | 15724 +++++++- .../scripts/quality.sh | 7 +- .../study.yaml | 8 +- .../tests/customer/expected.yaml | 1 + .../tests/customer/inputs.yaml | 1 + .../tests/development/expected.yaml | 1 + .../tests/development/inputs.yaml | 1 + .../tests/gcp/expected.yaml | 310 - .../tests/gcp/inputs.yaml | 1 - .../tests/gcp/test.yaml | 21 - .../tests/hyperscaler/expected.yaml | 1 + .../tests/hyperscaler/inputs.yaml | 1 + .../tests/kubernetes/expected.yaml | 340 - .../tests/kubernetes/inputs.yaml | 1 - .../tests/local/expected.yaml | 1 + .../tests/local/inputs.yaml | 1 + .../tests/os-large/expected.yaml | 402 - .../tests/os-large/inputs.yaml | 2 - .../tests/os-large/test.yaml | 21 - .../tests/os-medium/expected.yaml | 402 - .../tests/os-medium/inputs.yaml | 2 - .../tests/os-medium/test.yaml | 21 - .../variable-service-template.yaml | 84 +- .../dialects/unfurl/extended/nodes.ts | 14 + src/normative/types/core/artifacts.ts | 7 + src/normative/types/core/nodes.ts | 17 +- src/normative/types/extended/nodes.ts | 32 +- .../bucket/gcp-cloudstorage/ansible/index.ts | 71 + .../bucket/gcp-cloudstorage/index.ts | 4 + .../gcp-cloudstorage/terraform/index.ts | 72 + .../plugins/rules/generators/bucket/index.ts | 4 + .../generators/bucket/minio/asterisk/index.ts | 4 + .../asterisk/local-machine/ansible/index.ts | 59 + .../minio/asterisk/local-machine/index.ts | 4 + .../asterisk/local-machine/terraform/index.ts | 45 + .../asterisk/remote-machine/ansible/index.ts | 59 + .../minio/asterisk/remote-machine/index.ts | 4 + .../remote-machine/terraform/index.ts | 49 + .../rules/generators/bucket/minio/index.ts | 4 + .../minio/kubernetes-cluster/ansible/index.ts | 59 + .../bucket/minio/kubernetes-cluster/index.ts | 4 + .../kubernetes-cluster/terraform/index.ts | 49 + .../rules/generators/docker-engine/index.ts | 3 +- .../local-machine/ansible/index.ts | 160 + .../docker-engine/local-machine/index.ts | 4 + .../local-machine/terraform/index.ts | 149 + .../plugins/rules/generators/index.ts | 4 + .../mysql-dbms/docker-engine/index.ts | 3 +- .../local-machine/ansible/index.ts | 101 + .../local-machine/compose/index.ts | 124 + .../docker-engine/local-machine/index.ts | 5 + .../local-machine/terraform/index.ts | 95 + .../mysql-dbms-image/docker-engine/index.ts | 3 +- .../local-machine/ansible/index.ts | 90 + .../local-machine/compose/index.ts | 135 + .../docker-engine/local-machine/index.ts | 5 + .../local-machine/terraform/index.ts | 105 + .../cache-image/docker-engine/index.ts | 4 + .../local-machine/ansible/index.ts | 81 + .../local-machine/compose/index.ts | 112 + .../docker-engine/local-machine/index.ts | 5 + .../local-machine/terraform/index.ts | 84 + .../remote-machine/ansible/index.ts | 93 + .../remote-machine/compose/index.ts | 123 + .../docker-engine/remote-machine/index.ts | 5 + .../remote-machine/terraform/index.ts | 102 + .../gcp-memorystore/ansible/index.ts | 71 + .../cache-image/gcp-memorystore/index.ts | 4 + .../gcp-memorystore/terraform/index.ts | 73 + .../redis-server/cache-image/index.ts | 5 + .../kubernetes-cluster/ansible/index.ts | 58 + .../cache-image/kubernetes-cluster/index.ts | 6 + .../kubernetes-cluster/terraform/index.ts | 49 + .../rules/generators/redis-server/index.ts | 3 + .../docker-image/docker-engine/index.ts | 3 +- .../local-machine/ansible/index.ts | 79 + .../local-machine/compose/index.ts | 110 + .../docker-engine/local-machine/index.ts | 5 + .../local-machine/terraform/index.ts | 82 + 84 files changed, 52889 insertions(+), 1658 deletions(-) create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/expected.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/inputs.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/expected.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/inputs.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/expected.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/inputs.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/test.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/expected.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/inputs.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/expected.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/inputs.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/expected.yaml create mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/inputs.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/expected.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/inputs.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/test.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/expected.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/inputs.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/test.yaml create mode 100644 src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/index.ts create mode 100644 src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/terraform/index.ts create mode 100644 src/technologies/plugins/rules/generators/bucket/index.ts create mode 100644 src/technologies/plugins/rules/generators/bucket/minio/asterisk/index.ts create mode 100644 src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/terraform/index.ts create mode 100644 src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/terraform/index.ts create mode 100644 src/technologies/plugins/rules/generators/bucket/minio/index.ts create mode 100644 src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/index.ts create mode 100644 src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/terraform/index.ts create mode 100644 src/technologies/plugins/rules/generators/docker-engine/local-machine/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/docker-engine/local-machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/docker-engine/local-machine/terraform/index.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/compose/index.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/terraform/index.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/compose/index.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/terraform/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/compose/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/terraform/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/compose/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/terraform/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/terraform/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts create mode 100644 src/technologies/plugins/rules/generators/redis-server/index.ts create mode 100644 src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/compose/index.ts create mode 100644 src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/terraform/index.ts diff --git a/docs/docs/variability4tosca/rules/index.md b/docs/docs/variability4tosca/rules/index.md index 3e2df59714..9a282f1214 100644 --- a/docs/docs/variability4tosca/rules/index.md +++ b/docs/docs/variability4tosca/rules/index.md @@ -65,6 +65,86 @@ We assess the deployment quality of the following scenarios. ### Scenario #1 +In this scenario, the node template "component" of node type [bucket](/normative#bucket){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [gcp.cloudstorage](/normative#gcpcloudstorage){target=_blank}. + +
component(bucket)host 1(gcp.cloudstorage)host
+ + +!!! info "Ansible (Quality: 0.5)" + Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. + + + +### Scenario #2 + +In this scenario, the node template "component" of node type [bucket](/normative#bucket){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [minio.server](/normative#minioserver){target=_blank}, which is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 3" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(bucket)host 1(minio.server)...host 3(local.machine)hosthosthost
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. + + + +### Scenario #3 + +In this scenario, the node template "component" of node type [bucket](/normative#bucket){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [minio.server](/normative#minioserver){target=_blank}, which is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 3" of node type [remote.machine](/normative#remotemachine){target=_blank}. + +
component(bucket)host 1(minio.server)...host 3(remote.machine)hosthosthost
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. + + + +### Scenario #4 + +In this scenario, the node template "component" of node type [bucket](/normative#bucket){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [minio.server](/normative#minioserver){target=_blank}, which is hosted on the node template "host 2" of node type [kubernetes.cluster](/normative#kubernetescluster){target=_blank}. + +
component(bucket)host 1(minio.server)host 2(kubernetes.cluster)hosthost
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. + + + +### Scenario #5 + +In this scenario, the node template "component" of node type [docker.engine](/normative#dockerengine){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(docker.engine)host 1(local.machine)host
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! failure "Terraform (Quality: 0)" + Ansible is more specialized. Also using provisioners is a "last resort". + + + +### Scenario #6 + In this scenario, the node template "component" of node type [docker.engine](/normative#dockerengine){target=_blank} is deployed. The node template is hosted on the node template "host 1" of node type [remote.machine](/normative#remotemachine){target=_blank}. @@ -79,7 +159,7 @@ The node template is hosted on the node template "host 1" of node type [remote.m -### Scenario #2 +### Scenario #7 In this scenario, the node template "component" of node type [gcp.service](/normative#gcpservice){target=_blank} is deployed. The scenario does not require a specific hosting. @@ -95,7 +175,7 @@ The scenario does not require a specific hosting. -### Scenario #3 +### Scenario #8 In this scenario, the node template "component" of node type [ingress](/normative#ingress){target=_blank} is deployed. The node template is hosted on the node template "host 1" of node type [kubernetes.cluster](/normative#kubernetescluster){target=_blank}. @@ -114,7 +194,7 @@ The node template is hosted on the node template "host 1" of node type [kubernet -### Scenario #4 +### Scenario #9 In this scenario, the node template "component" of node type [ingress](/normative#ingress){target=_blank} is deployed. The node template is hosted on the node template "host 1" of node type [remote.machine](/normative#remotemachine){target=_blank}. @@ -130,7 +210,26 @@ The node template is hosted on the node template "host 1" of node type [remote.m -### Scenario #5 +### Scenario #10 + +In this scenario, the node template "component" of node type [mysql.database](/normative#mysqldatabase){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [mysql.dbms](/normative#mysqldbms){target=_blank}, which is hosted on the node template "host 2" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 3" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(local.machine)hosthosthost
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! info "Terraform (Quality: 0.5)" + Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. + +!!! failure "Docker Compose (Quality: 0)" + One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. + + + +### Scenario #11 In this scenario, the node template "component" of node type [mysql.database](/normative#mysqldatabase){target=_blank} is deployed. The node template is hosted on the node template "host 1" of node type [mysql.dbms](/normative#mysqldbms){target=_blank}, which is hosted on the node template "host 2" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 3" of node type [remote.machine](/normative#remotemachine){target=_blank}. @@ -149,7 +248,7 @@ The node template is hosted on the node template "host 1" of node type [mysql.db -### Scenario #6 +### Scenario #12 In this scenario, the node template "component" of node type [mysql.database](/normative#mysqldatabase){target=_blank} is deployed. The node template is hosted on the node template "host 1" of node type [mysql.dbms](/normative#mysqldbms){target=_blank}, which is hosted on the node template "host 2" of node type [gcp.cloudsql](/normative#gcpcloudsql){target=_blank}. @@ -165,7 +264,7 @@ The node template is hosted on the node template "host 1" of node type [mysql.db -### Scenario #7 +### Scenario #13 In this scenario, the node template "component" of node type [mysql.database](/normative#mysqldatabase){target=_blank} is deployed. The node template is hosted on the node template "host 1" of node type [mysql.dbms](/normative#mysqldbms){target=_blank}, which is hosted on the node template "host 2" of node type [kubernetes.cluster](/normative#kubernetescluster){target=_blank}. @@ -184,7 +283,7 @@ The node template is hosted on the node template "host 1" of node type [mysql.db -### Scenario #8 +### Scenario #14 In this scenario, the node template "component" of node type [mysql.database](/normative#mysqldatabase){target=_blank} is deployed. The node template is hosted on the node template "host 1" of node type [mysql.dbms](/normative#mysqldbms){target=_blank}, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. @@ -200,7 +299,27 @@ The node template is hosted on the node template "host 1" of node type [mysql.db -### Scenario #9 +### Scenario #15 + +In this scenario, the node template "component" of node type [mysql.dbms](/normative#mysqldbms){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [dbms.image](/normative#dbmsimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(local.machine)hosthost
+ + +!!! info "Ansible (Quality: 0.5)" + Docker Compose is more specialized + +!!! info "Terraform (Quality: 0.5)" + Docker Compose is more specialized. + +!!! success "Docker Compose (Quality: 1)" + Docker is the underlying technology. + + + +### Scenario #16 In this scenario, the node template "component" of node type [mysql.dbms](/normative#mysqldbms){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [dbms.image](/normative#dbmsimage){target=_blank}. @@ -220,7 +339,7 @@ The node template is hosted on the node template "host 1" of node type [docker.e -### Scenario #10 +### Scenario #17 In this scenario, the node template "component" of node type [mysql.dbms](/normative#mysqldbms){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [dbms.image](/normative#dbmsimage){target=_blank}. @@ -237,7 +356,7 @@ The node template is hosted on the node template "host 1" of node type [gcp.clou -### Scenario #11 +### Scenario #18 In this scenario, the node template "component" of node type [mysql.dbms](/normative#mysqldbms){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [dbms.image](/normative#dbmsimage){target=_blank}. @@ -257,7 +376,7 @@ The node template is hosted on the node template "host 1" of node type [kubernet -### Scenario #12 +### Scenario #19 In this scenario, the node template "component" of node type [mysql.dbms](/normative#mysqldbms){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [dbms.image](/normative#dbmsimage){target=_blank}. @@ -274,7 +393,97 @@ The node template is hosted on the node template "host 1" of node type [remote.m -### Scenario #13 +### Scenario #20 + +In this scenario, the node template "component" of node type [bucket](/normative#bucket){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [gcp.memorystore](/normative#gcpmemorystore){target=_blank}. + +
component(bucket)artifact(cache.image)host 1(gcp.memorystore)host
+ + +!!! info "Ansible (Quality: 0.5)" + Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. + + + +### Scenario #21 + +In this scenario, the node template "component" of node type [redis.server](/normative#redisserver){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(local.machine)hosthost
+ + +!!! info "Ansible (Quality: 0.5)" + Docker Compose is more specialized. + +!!! info "Terraform (Quality: 0.5)" + Docker Compose is more specialized. + +!!! success "Docker Compose (Quality: 1)" + Docker is the underlying technology. + + + +### Scenario #22 + +In this scenario, the node template "component" of node type [redis.server](/normative#redisserver){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. + +
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(remote.machine)hosthost
+ + +!!! info "Ansible (Quality: 0.5)" + Docker Compose is more specialized. + +!!! info "Terraform (Quality: 0.5)" + Docker Compose is more specialized. + +!!! success "Docker Compose (Quality: 1)" + Docker is the underlying technology. + + + +### Scenario #23 + +In this scenario, the node template "component" of node type [redis.server](/normative#redisserver){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [kubernetes.cluster](/normative#kubernetescluster){target=_blank}. + +
component(redis.server)host 1(kubernetes.cluster)host
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. + + + +### Scenario #24 + +In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [docker.image](/normative#dockerimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(local.machine)hosthost
+ + +!!! info "Ansible (Quality: 0.5)" + Docker Compose is more specialized. + +!!! info "Terraform (Quality: 0.5)" + Docker Compose is more specialized. + +!!! success "Docker Compose (Quality: 1)" + Docker is the underlying technology. + + + +### Scenario #25 In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [docker.image](/normative#dockerimage){target=_blank}. @@ -294,7 +503,7 @@ The node template is hosted on the node template "host 1" of node type [docker.e -### Scenario #14 +### Scenario #26 In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [docker.image](/normative#dockerimage){target=_blank}. @@ -311,7 +520,7 @@ The node template is hosted on the node template "host 1" of node type [gcp.clou -### Scenario #15 +### Scenario #27 In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [docker.image](/normative#dockerimage){target=_blank}. @@ -331,7 +540,7 @@ The node template is hosted on the node template "host 1" of node type [kubernet -### Scenario #16 +### Scenario #28 In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [tar.archive](/normative#tararchive){target=_blank}. @@ -348,7 +557,7 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w -### Scenario #17 +### Scenario #29 In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [zip.archive](/normative#ziparchive){target=_blank}. @@ -365,7 +574,7 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w -### Scenario #18 +### Scenario #30 In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [zip.archive](/normative#ziparchive){target=_blank}. @@ -382,7 +591,7 @@ The node template is hosted on the node template "host 1" of node type [gcp.appe -### Scenario #19 +### Scenario #31 In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [apt.package](/normative#aptpackage){target=_blank}. @@ -396,7 +605,7 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w -### Scenario #20 +### Scenario #32 In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [tar.archive](/normative#tararchive){target=_blank}. @@ -413,7 +622,7 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w -### Scenario #21 +### Scenario #33 In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [zip.archive](/normative#ziparchive){target=_blank}. @@ -430,7 +639,7 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w -### Scenario #22 +### Scenario #34 In this scenario, the node template "component" of node type [virtual.machine](/normative#virtualmachine){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [machine.image](/normative#machineimage){target=_blank}. @@ -447,7 +656,21 @@ The node template is hosted on the node template "host 1" of node type [openstac -### Scenario #23 +### Scenario #35 + +In this scenario, the node template "component" of node type [redis.server](/normative#redisserver){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [gcp.memorystore](/normative#gcpmemorystore){target=_blank}. + +
component(redis.server)artifact(cache.image)host 1(gcp.memorystore)host
+ + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. + + + +### Scenario #36 In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [apt.archive](/normative#aptarchive){target=_blank}. @@ -470,6 +693,61 @@ This appendix contains the deployment technology rules. ### Rule #1 | Attribute | Value | | --- | --- | +| Identifier | bucket::ansible@gcp.cloudstorage | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [gcp.cloudstorage](/normative#gcpcloudstorage){target=_blank} | +| Quality | 0.5 | +| Reason | Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. | +| Details | | +| Graph |
component(bucket)host 1(gcp.cloudstorage)host
| + +### Rule #2 +| Attribute | Value | +| --- | --- | +| Identifier | bucket::ansible@minio.server->*->local.machine | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [minio.server](/normative#minioserver){target=_blank} -> * -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | | +| Graph |
component(bucket)host 1(minio.server)...host 3(local.machine)hosthosthost
| + +### Rule #3 +| Attribute | Value | +| --- | --- | +| Identifier | bucket::ansible@minio.server->*->remote.machine | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [minio.server](/normative#minioserver){target=_blank} -> * -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | | +| Graph |
component(bucket)host 1(minio.server)...host 3(remote.machine)hosthosthost
| + +### Rule #4 +| Attribute | Value | +| --- | --- | +| Identifier | bucket::ansible@minio.server->kubernetes.cluster | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [minio.server](/normative#minioserver){target=_blank} -> [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | | +| Graph |
component(bucket)host 1(minio.server)host 2(kubernetes.cluster)hosthost
| + +### Rule #5 +| Attribute | Value | +| --- | --- | +| Identifier | docker.engine::ansible@local.machine | +| Component | [docker.engine](/normative#dockerengine){target=_blank} | +| Hosting | [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | "ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks | +| Graph |
component(docker.engine)host 1(local.machine)host
| + +### Rule #6 +| Attribute | Value | +| --- | --- | | Identifier | docker.engine::ansible@remote.machine | | Component | [docker.engine](/normative#dockerengine){target=_blank} | | Hosting | [remote.machine](/normative#remotemachine){target=_blank} | @@ -478,7 +756,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks | | Graph |
component(docker.engine)host 1(remote.machine)host
| -### Rule #2 +### Rule #7 | Attribute | Value | | --- | --- | | Identifier | gcp.service::ansible | @@ -488,7 +766,7 @@ This appendix contains the deployment technology rules. | Details | "google.cloud.gcp_serviceusage_service" task | | Graph |
component(gcp.service)
| -### Rule #3 +### Rule #8 | Attribute | Value | | --- | --- | | Identifier | ingress::ansible@kubernetes.cluster | @@ -499,7 +777,7 @@ This appendix contains the deployment technology rules. | Details | "kubernetes.core.k8s" task | | Graph |
component(ingress)host 1(kubernetes.cluster)host
| -### Rule #4 +### Rule #9 | Attribute | Value | | --- | --- | | Identifier | ingress::ansible@remote.machine | @@ -510,7 +788,18 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", "ansible.builtin.copy", and "ansible.builtin.systemd" tasks | | Graph |
component(ingress)host 1(remote.machine)host
| -### Rule #5 +### Rule #10 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.database::ansible@mysql.dbms->docker.engine->local.machine | +| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | | +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(local.machine)hosthosthost
| + +### Rule #11 | Attribute | Value | | --- | --- | | Identifier | mysql.database::ansible@mysql.dbms->docker.engine->remote.machine | @@ -521,7 +810,7 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(remote.machine)hosthosthost
| -### Rule #6 +### Rule #12 | Attribute | Value | | --- | --- | | Identifier | mysql.database::ansible@mysql.dbms->gcp.cloudsql | @@ -532,7 +821,7 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(gcp.cloudsql)hosthost
| -### Rule #7 +### Rule #13 | Attribute | Value | | --- | --- | | Identifier | mysql.database::ansible@mysql.dbms->kubernetes.cluster | @@ -543,7 +832,7 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(kubernetes.cluster)hosthost
| -### Rule #8 +### Rule #14 | Attribute | Value | | --- | --- | | Identifier | mysql.database::ansible@mysql.dbms->remote.machine | @@ -554,7 +843,19 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(remote.machine)hosthost
| -### Rule #9 +### Rule #15 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::ansible@docker.engine->local.machine | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized | +| Details | "community.docker.docker_container" task | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #16 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::ansible@docker.engine->remote.machine | @@ -566,7 +867,7 @@ This appendix contains the deployment technology rules. | Details | "community.docker.docker_container" task | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #10 +### Rule #17 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::ansible@gcp.cloudsql | @@ -578,7 +879,7 @@ This appendix contains the deployment technology rules. | Details | "google.cloud.gcp_sql_instance" and "google.cloud.gcp_sql_user" tasks | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(gcp.cloudsql)host
| -### Rule #11 +### Rule #18 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::ansible@kubernetes.cluster | @@ -590,7 +891,7 @@ This appendix contains the deployment technology rules. | Details | "kubernetes.core.k8s" tasks | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(kubernetes.cluster)host
| -### Rule #12 +### Rule #19 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::ansible@remote.machine | @@ -602,7 +903,66 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(remote.machine)host
| -### Rule #13 +### Rule #20 +| Attribute | Value | +| --- | --- | +| Identifier | bucket#cache.image::ansible@gcp.memorystore | +| Component | [bucket](/normative#bucket){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [gcp.memorystore](/normative#gcpmemorystore){target=_blank} | +| Quality | 0.5 | +| Reason | Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. | +| Details | | +| Graph |
component(bucket)artifact(cache.image)host 1(gcp.memorystore)host
| + +### Rule #21 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::ansible@docker.engine->local.machine | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized. | +| Details | "community.docker.docker_container" task | +| Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #22 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::ansible@docker.engine->remote.machine | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized. | +| Details | "community.docker.docker_container" task | +| Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(remote.machine)hosthost
| + +### Rule #23 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server::ansible@kubernetes.cluster | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | | +| Graph |
component(redis.server)host 1(kubernetes.cluster)host
| + +### Rule #24 +| Attribute | Value | +| --- | --- | +| Identifier | service.application#docker.image::ansible@docker.engine->local.machine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized. | +| Details | "community.docker.docker_container" task | +| Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #25 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::ansible@docker.engine->remote.machine | @@ -614,7 +974,7 @@ This appendix contains the deployment technology rules. | Details | "community.docker.docker_container" task | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #14 +### Rule #26 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::ansible@gcp.cloudrun | @@ -626,7 +986,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.shell", "ansible.builtin.tempfile", and "ansible.builtin.copy" tasks | | Graph |
component(service.application)artifact(docker.image)host 1(gcp.cloudrun)host
| -### Rule #15 +### Rule #27 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::ansible@kubernetes.cluster | @@ -638,7 +998,7 @@ This appendix contains the deployment technology rules. | Details | "kubernetes.core.k8s" tasks | | Graph |
component(service.application)artifact(docker.image)host 1(kubernetes.cluster)host
| -### Rule #16 +### Rule #28 | Attribute | Value | | --- | --- | | Identifier | service.application#tar.archive::ansible@*->remote.machine | @@ -650,7 +1010,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements | | Graph |
component(service.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #17 +### Rule #29 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::ansible@*->remote.machine | @@ -662,7 +1022,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements | | Graph |
component(service.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #18 +### Rule #30 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::ansible@gcp.appengine | @@ -674,7 +1034,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.shell", "ansible.builtin.tempfile", "ansible.builtin.unarchive", and "ansible.builtin.copy" tasks | | Graph |
component(service.application)artifact(zip.archive)host 1(gcp.appengine)host
| -### Rule #19 +### Rule #31 | Attribute | Value | | --- | --- | | Identifier | software.application#apt.package::ansible@*->remote.machine | @@ -686,7 +1046,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements | | Graph |
component(software.application)artifact(apt.package)...host 2(remote.machine)hosthost
| -### Rule #20 +### Rule #32 | Attribute | Value | | --- | --- | | Identifier | software.application#tar.archive::ansible@*->remote.machine | @@ -698,7 +1058,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | | Graph |
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #21 +### Rule #33 | Attribute | Value | | --- | --- | | Identifier | software.application#zip.archive::ansible@*->remote.machine | @@ -710,7 +1070,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | | Graph |
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #22 +### Rule #34 | Attribute | Value | | --- | --- | | Identifier | virtual.machine#machine.image::ansible@openstack.provider | @@ -724,7 +1084,62 @@ This appendix contains the deployment technology rules. -### Rule #23 +### Rule #35 +| Attribute | Value | +| --- | --- | +| Identifier | bucket::terraform@gcp.cloudstorage | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [gcp.cloudstorage](/normative#gcpcloudstorage){target=_blank} | +| Quality | 1 | +| Reason | Terraform provides a declarative module. | +| Details | | +| Graph |
component(bucket)host 1(gcp.cloudstorage)host
| + +### Rule #36 +| Attribute | Value | +| --- | --- | +| Identifier | bucket::terraform@minio.server->*->local.machine | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [minio.server](/normative#minioserver){target=_blank} -> * -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Terraform provides a declarative module. | +| Details | | +| Graph |
component(bucket)host 1(minio.server)...host 3(local.machine)hosthosthost
| + +### Rule #37 +| Attribute | Value | +| --- | --- | +| Identifier | bucket::terraform@minio.server->*->remote.machine | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [minio.server](/normative#minioserver){target=_blank} -> * -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Terraform provides a declarative module. | +| Details | | +| Graph |
component(bucket)host 1(minio.server)...host 3(remote.machine)hosthosthost
| + +### Rule #38 +| Attribute | Value | +| --- | --- | +| Identifier | bucket::terraform@minio.server->kubernetes.cluster | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [minio.server](/normative#minioserver){target=_blank} -> [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Quality | 1 | +| Reason | Terraform provides a declarative module. | +| Details | | +| Graph |
component(bucket)host 1(minio.server)host 2(kubernetes.cluster)hosthost
| + +### Rule #39 +| Attribute | Value | +| --- | --- | +| Identifier | docker.engine::terraform@local.machine | +| Component | [docker.engine](/normative#dockerengine){target=_blank} | +| Hosting | [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0 | +| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | +| Details | "local-exec" provider | +| Graph |
component(docker.engine)host 1(local.machine)host
| + +### Rule #40 | Attribute | Value | | --- | --- | | Identifier | docker.engine::terraform@remote.machine | @@ -735,7 +1150,7 @@ This appendix contains the deployment technology rules. | Details | "remote-exec" provider | | Graph |
component(docker.engine)host 1(remote.machine)host
| -### Rule #24 +### Rule #41 | Attribute | Value | | --- | --- | | Identifier | gcp.service::terraform | @@ -745,7 +1160,7 @@ This appendix contains the deployment technology rules. | Details | "google_project_service" resource | | Graph |
component(gcp.service)
| -### Rule #25 +### Rule #42 | Attribute | Value | | --- | --- | | Identifier | ingress::terraform@kubernetes.cluster | @@ -756,7 +1171,7 @@ This appendix contains the deployment technology rules. | Details | "kubernetes_service_v1" resource | | Graph |
component(ingress)host 1(kubernetes.cluster)host
| -### Rule #26 +### Rule #43 | Attribute | Value | | --- | --- | | Identifier | ingress::terraform@remote.machine | @@ -767,7 +1182,18 @@ This appendix contains the deployment technology rules. | Details | "terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner | | Graph |
component(ingress)host 1(remote.machine)host
| -### Rule #27 +### Rule #44 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.database::terraform@mysql.dbms->docker.engine->local.machine | +| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. | +| Details | | +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(local.machine)hosthosthost
| + +### Rule #45 | Attribute | Value | | --- | --- | | Identifier | mysql.database::terraform@mysql.dbms->docker.engine->remote.machine | @@ -778,7 +1204,7 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(remote.machine)hosthosthost
| -### Rule #28 +### Rule #46 | Attribute | Value | | --- | --- | | Identifier | mysql.database::terraform@mysql.dbms->gcp.cloudsql | @@ -789,7 +1215,7 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(gcp.cloudsql)hosthost
| -### Rule #29 +### Rule #47 | Attribute | Value | | --- | --- | | Identifier | mysql.database::terraform@mysql.dbms->kubernetes.cluster | @@ -800,7 +1226,7 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(kubernetes.cluster)hosthost
| -### Rule #30 +### Rule #48 | Attribute | Value | | --- | --- | | Identifier | mysql.database::terraform@mysql.dbms->remote.machine | @@ -811,7 +1237,19 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(remote.machine)hosthost
| -### Rule #31 +### Rule #49 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::terraform@docker.engine->local.machine | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized. | +| Details | "docker_container" and "docker_image" resources | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #50 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::terraform@docker.engine->remote.machine | @@ -823,7 +1261,7 @@ This appendix contains the deployment technology rules. | Details | "docker_container" and "docker_image" resources | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #32 +### Rule #51 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::terraform@gcp.cloudsql | @@ -835,7 +1273,7 @@ This appendix contains the deployment technology rules. | Details | "google_sql_database_instance" and "google_sql_user" resources | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(gcp.cloudsql)host
| -### Rule #33 +### Rule #52 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::terraform@kubernetes.cluster | @@ -847,7 +1285,7 @@ This appendix contains the deployment technology rules. | Details | "kubernetes_deployment_v1" and "kubernetes_service_v1" resources | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(kubernetes.cluster)host
| -### Rule #34 +### Rule #53 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::terraform@remote.machine | @@ -859,7 +1297,66 @@ This appendix contains the deployment technology rules. | Details | "terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(remote.machine)host
| -### Rule #35 +### Rule #54 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::terraform@gcp.memorystore | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [gcp.memorystore](/normative#gcpmemorystore){target=_blank} | +| Quality | 1 | +| Reason | Terraform provides a declarative module. | +| Details | | +| Graph |
component(redis.server)artifact(cache.image)host 1(gcp.memorystore)host
| + +### Rule #55 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::terraform@docker.engine->local.machine | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized. | +| Details | "docker_container" and "docker_image" resources | +| Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #56 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::terraform@docker.engine->remote.machine | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized. | +| Details | "docker_container" and "docker_image" resources | +| Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(remote.machine)hosthost
| + +### Rule #57 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server::terraform@kubernetes.cluster | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Quality | 1 | +| Reason | Terraform provides a declarative module. | +| Details | | +| Graph |
component(redis.server)host 1(kubernetes.cluster)host
| + +### Rule #58 +| Attribute | Value | +| --- | --- | +| Identifier | service.application#docker.image::terraform@docker.engine->local.machine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized. | +| Details | "docker_container" and "docker_image" resources | +| Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #59 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::terraform@docker.engine->remote.machine | @@ -871,7 +1368,7 @@ This appendix contains the deployment technology rules. | Details | "docker_container" and "docker_image" resources | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #36 +### Rule #60 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::terraform@gcp.cloudrun | @@ -883,7 +1380,7 @@ This appendix contains the deployment technology rules. | Details | "google_cloud_run_v2_service" and "google_cloud_run_service_iam_binding" resources | | Graph |
component(service.application)artifact(docker.image)host 1(gcp.cloudrun)host
| -### Rule #37 +### Rule #61 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::terraform@kubernetes.cluster | @@ -895,7 +1392,7 @@ This appendix contains the deployment technology rules. | Details | "kubernetes_deployment_v1" and "kubernetes_service_v1" resources | | Graph |
component(service.application)artifact(docker.image)host 1(kubernetes.cluster)host
| -### Rule #38 +### Rule #62 | Attribute | Value | | --- | --- | | Identifier | service.application#tar.archive::terraform@*->remote.machine | @@ -907,7 +1404,7 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(service.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #39 +### Rule #63 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::terraform@*->remote.machine | @@ -919,7 +1416,7 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(service.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #40 +### Rule #64 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::terraform@gcp.appengine | @@ -931,7 +1428,7 @@ This appendix contains the deployment technology rules. | Details | "google_app_engine_standard_app_version", "google_project_iam_member", "google_service_account", "google_storage_bucket", and "google_storage_bucket_object" resources | | Graph |
component(service.application)artifact(zip.archive)host 1(gcp.appengine)host
| -### Rule #41 +### Rule #65 | Attribute | Value | | --- | --- | | Identifier | software.application#apt.archive::terraform@*->remote.machine | @@ -943,7 +1440,7 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload scripts and "remote-exec" to execute scripts | | Graph |
component(software.application)artifact(apt.archive)...host 2(remote.machine)hosthost
| -### Rule #42 +### Rule #66 | Attribute | Value | | --- | --- | | Identifier | software.application#tar.archive::terraform@*->remote.machine | @@ -955,7 +1452,7 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #43 +### Rule #67 | Attribute | Value | | --- | --- | | Identifier | software.application#zip.archive::terraform@*->remote.machine | @@ -967,7 +1464,7 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #44 +### Rule #68 | Attribute | Value | | --- | --- | | Identifier | virtual.machine#machine.image::terraform@openstack.provider | @@ -981,7 +1478,7 @@ This appendix contains the deployment technology rules. -### Rule #45 +### Rule #69 | Attribute | Value | | --- | --- | | Identifier | ingress::kubernetes@kubernetes.cluster | @@ -992,7 +1489,7 @@ This appendix contains the deployment technology rules. | Details | Kubernetes manifest generated and applied | | Graph |
component(ingress)host 1(kubernetes.cluster)host
| -### Rule #46 +### Rule #70 | Attribute | Value | | --- | --- | | Identifier | mysql.database::kubernetes@mysql.dbms->kubernetes.cluster | @@ -1003,7 +1500,7 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(kubernetes.cluster)hosthost
| -### Rule #47 +### Rule #71 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::kubernetes@kubernetes.cluster | @@ -1015,7 +1512,7 @@ This appendix contains the deployment technology rules. | Details | Kubernetes manifest generated and applied | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(kubernetes.cluster)host
| -### Rule #48 +### Rule #72 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::kubernetes@kubernetes.cluster | @@ -1029,7 +1526,18 @@ This appendix contains the deployment technology rules. -### Rule #49 +### Rule #73 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.database::compose@mysql.dbms->docker.engine->local.machine | +| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0 | +| Reason | One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. | +| Details | | +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(local.machine)hosthosthost
| + +### Rule #74 | Attribute | Value | | --- | --- | | Identifier | mysql.database::compose@mysql.dbms->docker.engine->remote.machine | @@ -1040,7 +1548,19 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(remote.machine)hosthosthost
| -### Rule #50 +### Rule #75 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::compose@docker.engine->local.machine | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Docker is the underlying technology. | +| Details | docker-compose manifest generated and applied | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #76 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::compose@docker.engine->remote.machine | @@ -1052,7 +1572,43 @@ This appendix contains the deployment technology rules. | Details | docker-compose manifest generated and applied | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #51 +### Rule #77 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::compose@docker.engine->local.machine | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Docker is the underlying technology. | +| Details | docker compose manifest generated and applied | +| Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #78 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::compose@docker.engine->remote.machine | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Docker is the underlying technology. | +| Details | docker compose manifest generated and applied | +| Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(remote.machine)hosthost
| + +### Rule #79 +| Attribute | Value | +| --- | --- | +| Identifier | service.application#docker.image::compose@docker.engine->local.machine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Docker is the underlying technology. | +| Details | docker compose manifest generated and applied | +| Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #80 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::compose@docker.engine->remote.machine | diff --git a/docs/docs/variability4tosca/rules/technology-rules.yaml b/docs/docs/variability4tosca/rules/technology-rules.yaml index 41b401cf87..f58ff02c68 100644 --- a/docs/docs/variability4tosca/rules/technology-rules.yaml +++ b/docs/docs/variability4tosca/rules/technology-rules.yaml @@ -1,4 +1,35 @@ ansible: + - component: bucket + hosting: + - gcp.cloudstorage + weight: 0.5 + reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. + - component: bucket + hosting: + - minio.server + - '*' + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + - component: bucket + hosting: + - minio.server + - '*' + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + - component: bucket + hosting: + - minio.server + - kubernetes.cluster + weight: 1 + reason: Primary use case due to the specialization of Ansible. + - component: docker.engine + hosting: + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks' - component: docker.engine hosting: - remote.machine @@ -22,6 +53,13 @@ ansible: weight: 1 reason: Primary use case due to the specialization of Ansible. details: '"ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", "ansible.builtin.copy", and "ansible.builtin.systemd" tasks' + - component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. - component: mysql.database hosting: - mysql.dbms @@ -47,6 +85,14 @@ ansible: - remote.machine weight: 1 reason: Primary use case due to the specialization of Ansible. + - component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized + details: '"community.docker.docker_container" task' - component: mysql.dbms artifact: dbms.image hosting: @@ -76,6 +122,41 @@ ansible: weight: 1 reason: Primary use case due to the specialization of Ansible. details: '"ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks' + - component: bucket + artifact: cache.image + hosting: + - gcp.memorystore + weight: 0.5 + reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. + - component: redis.server + artifact: cache.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"community.docker.docker_container" task' + - component: redis.server + artifact: cache.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"community.docker.docker_container" task' + - component: redis.server + hosting: + - kubernetes.cluster + weight: 1 + reason: Primary use case due to the specialization of Ansible. + - component: service.application + artifact: docker.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"community.docker.docker_container" task' - component: service.application artifact: docker.image hosting: @@ -153,6 +234,37 @@ ansible: reason: Terraform is more specialized. details: '"openstack.cloud.security_group", "openstack.cloud.security_group_rule" and "openstack.cloud.server" tasks' terraform: + - component: bucket + hosting: + - gcp.cloudstorage + weight: 1 + reason: Terraform provides a declarative module. + - component: bucket + hosting: + - minio.server + - '*' + - local.machine + weight: 1 + reason: Terraform provides a declarative module. + - component: bucket + hosting: + - minio.server + - '*' + - remote.machine + weight: 1 + reason: Terraform provides a declarative module. + - component: bucket + hosting: + - minio.server + - kubernetes.cluster + weight: 1 + reason: Terraform provides a declarative module. + - component: docker.engine + hosting: + - local.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"local-exec" provider' - component: docker.engine hosting: - remote.machine @@ -176,6 +288,13 @@ terraform: weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' + - component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - local.machine + weight: 0.5 + reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. - component: mysql.database hosting: - mysql.dbms @@ -201,6 +320,14 @@ terraform: - remote.machine weight: 0.5 reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. + - component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' - component: mysql.dbms artifact: dbms.image hosting: @@ -230,6 +357,41 @@ terraform: weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' + - component: redis.server + artifact: cache.image + hosting: + - gcp.memorystore + weight: 1 + reason: Terraform provides a declarative module. + - component: redis.server + artifact: cache.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' + - component: redis.server + artifact: cache.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' + - component: redis.server + hosting: + - kubernetes.cluster + weight: 1 + reason: Terraform provides a declarative module. + - component: service.application + artifact: docker.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' - component: service.application artifact: docker.image hosting: @@ -334,6 +496,13 @@ kubernetes: reason: Kubernetes is the underlying technology. details: Kubernetes manifest generated and applied compose: + - component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - local.machine + weight: 0 + reason: One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. - component: mysql.database hosting: - mysql.dbms @@ -341,6 +510,14 @@ compose: - remote.machine weight: 0 reason: One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. + - component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - local.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker-compose manifest generated and applied - component: mysql.dbms artifact: dbms.image hosting: @@ -349,6 +526,30 @@ compose: weight: 1 reason: Docker is the underlying technology. details: docker-compose manifest generated and applied + - component: redis.server + artifact: cache.image + hosting: + - docker.engine + - local.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker compose manifest generated and applied + - component: redis.server + artifact: cache.image + hosting: + - docker.engine + - remote.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker compose manifest generated and applied + - component: service.application + artifact: docker.image + hosting: + - docker.engine + - local.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker compose manifest generated and applied - component: service.application artifact: docker.image hosting: diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/retailer.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/retailer.yaml index f14f4d9919..4e71d634ec 100644 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/retailer.yaml +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/retailer.yaml @@ -33,3 +33,31232 @@ node_types: retailer.service.global: derived_from: nodejs.service.application + + # [OPENTOSCA_VINTNER_GENERATION_MARK] + + ################################################################ + # + # WARNING: Do not edit! This following content is autogenerated! + # + ################################################################ + + retailer.frontend.dashboard~service.application#docker.image::ansible@docker.engine->local.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + retailer.frontend.dashboard~service.application#docker.image::ansible@docker.engine->remote.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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 }}' + retailer.frontend.dashboard~service.application#docker.image::ansible@gcp.cloudrun: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: touch service + register: service + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.service.yaml' + - name: create service + ansible.builtin.copy: + dest: '{{ service.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + apiVersion: serving.knative.dev/v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + labels: + cloud.googleapis.com/location: '{{ SELF.gcp_region }}' + annotations: + run.googleapis.com/ingress: all + spec: + template: + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + containerPort: '{{ SELF.application_port }}' + env: [] + - name: apply service + ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet + args: + executable: /bin/bash + - name: touch policy + register: policy + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.policy.yaml' + - name: fill policy + ansible.builtin.copy: + dest: '{{ policy.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + bindings: + - members: + - allUsers + role: roles/run.invoker + - name: apply policy + ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + - name: describe service + register: service_description + ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + retailer.frontend.dashboard~service.application#docker.image::ansible@kubernetes.cluster: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: create deployment + kubernetes.core.k8s: + wait: true + definition: + 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 }}' + - name: create service + kubernetes.core.k8s: + definition: + 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 + 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 }}' + retailer.frontend.dashboard~service.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.frontend.dashboard~service.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.frontend.dashboard~service.application#zip.archive::ansible@gcp.appengine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: enable GCP AppEngine + ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + register: app_create_command + failed_when: + - "'Created' not in app_create_command.stderr" + - "'already contains' not in app_create_command.stderr" + - name: create working directory + register: directory + ansible.builtin.tempfile: + state: directory + - name: extract deployment artifact in working directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ directory.path }}' + - name: create specification + ansible.builtin.copy: + dest: '{{ directory.path }}/app.yaml' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + instance_class: F1 + env_variables: {} + - name: create app + ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet + args: + executable: /bin/bash + - name: browse app + register: browse_app + ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ browse_app.stdout[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet + args: + executable: /bin/bash + retailer.frontend.dashboard~software.application#apt.package::ansible@*->remote.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.frontend.dashboard~software.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.frontend.dashboard~software.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.frontend.dashboard~service.application#docker.image::terraform@docker.engine->local.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.frontend.dashboard~service.application#docker.image::terraform@docker.engine->remote.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.frontend.dashboard~service.application#docker.image::terraform@gcp.cloudrun: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' + resource: + google_cloud_run_v2_service: + application: + - ingress: INGRESS_TRAFFIC_ALL + location: '{{ SELF.gcp_region }}' + name: '{{ SELF.application_name }}' + template: + - containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + container_port: '{{ SELF.application_port }}' + env: [] + google_cloud_run_service_iam_binding: + application: + - location: '{{ SELF.gcp_region }}' + members: + - allUsers + role: roles/run.invoker + service: '{{ SELF.application_name }}' + retailer.frontend.dashboard~service.application#docker.image::terraform@kubernetes.cluster: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_deployment_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - selector: + - match_labels: + app: '{{ SELF.application_name }}' + template: + - metadata: + - labels: + app: '{{ SELF.application_name }}' + spec: + - container: + - env: [] + image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + port: + - container_port: '{{ SELF.application_port }}' + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - port: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + target_port: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + retailer.frontend.dashboard~service.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.frontend.dashboard + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.frontend.dashboard {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.frontend.dashboard -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.frontend.dashboard.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.frontend.dashboard.sh + - sudo bash /tmp/configure-retailer.frontend.dashboard.sh + - sudo bash /tmp/start-retailer.frontend.dashboard.sh + - inline: + - sudo bash /tmp/stop-retailer.frontend.dashboard.sh + - sudo bash /tmp/delete-retailer.frontend.dashboard.sh + when: destroy + retailer.frontend.dashboard~service.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.frontend.dashboard + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.frontend.dashboard {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.frontend.dashboard -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.frontend.dashboard.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.frontend.dashboard.sh + - sudo bash /tmp/configure-retailer.frontend.dashboard.sh + - sudo bash /tmp/start-retailer.frontend.dashboard.sh + - inline: + - sudo bash /tmp/stop-retailer.frontend.dashboard.sh + - sudo bash /tmp/delete-retailer.frontend.dashboard.sh + when: destroy + retailer.frontend.dashboard~service.application#zip.archive::terraform@gcp.appengine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' + resource: + google_app_engine_standard_app_version: + app: + - delete_service_on_destroy: true + deployment: + - zip: + - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} + entrypoint: + - shell: '{{ SELF._management_start }}' + env_variables: {} + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + service_account: ${google_service_account.custom_service_account.email} + version_id: v1 + google_project_iam_member: + gae_api: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/compute.networkUser + storage_viewer: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/storage.objectViewer + google_service_account: + custom_service_account: + - account_id: '{{ SELF.application_name }}-account' + display_name: Custom Service Account + google_storage_bucket: + bucket: + - location: EU + name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' + google_storage_bucket_object: + object: + - bucket: ${google_storage_bucket.bucket.name} + name: object.zip + source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + retailer.frontend.dashboard~software.application#apt.archive::terraform@*->remote.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.frontend.dashboard {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-retailer.frontend.dashboard.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.frontend.dashboard.sh + - sudo bash /tmp/configure-retailer.frontend.dashboard.sh + - sudo bash /tmp/start-retailer.frontend.dashboard.sh + - inline: + - sudo bash /tmp/stop-retailer.frontend.dashboard.sh + - sudo bash /tmp/delete-retailer.frontend.dashboard.sh + when: destroy + retailer.frontend.dashboard~software.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.frontend.dashboard + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.frontend.dashboard {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.frontend.dashboard -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.frontend.dashboard.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.frontend.dashboard.sh + - sudo bash /tmp/configure-retailer.frontend.dashboard.sh + - sudo bash /tmp/start-retailer.frontend.dashboard.sh + - inline: + - sudo bash /tmp/stop-retailer.frontend.dashboard.sh + - sudo bash /tmp/delete-retailer.frontend.dashboard.sh + when: destroy + retailer.frontend.dashboard~software.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.frontend.dashboard + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.frontend.dashboard {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.frontend.dashboard -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.frontend.dashboard.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.frontend.dashboard.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.frontend.dashboard.sh + - sudo bash /tmp/configure-retailer.frontend.dashboard.sh + - sudo bash /tmp/start-retailer.frontend.dashboard.sh + - inline: + - sudo bash /tmp/stop-retailer.frontend.dashboard.sh + - sudo bash /tmp/delete-retailer.frontend.dashboard.sh + when: destroy + retailer.frontend.dashboard~service.application#docker.image::kubernetes@kubernetes.cluster: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: 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 }} 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 + retailer.frontend.dashboard~service.application#docker.image::compose@docker.engine->local.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 + retailer.frontend.dashboard~service.application#docker.image::compose@docker.engine->remote.machine: + derived_from: retailer.frontend.dashboard + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 }}' + retailer.frontend.terminal~service.application#docker.image::ansible@docker.engine->local.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + retailer.frontend.terminal~service.application#docker.image::ansible@docker.engine->remote.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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 }}' + retailer.frontend.terminal~service.application#docker.image::ansible@gcp.cloudrun: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: touch service + register: service + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.service.yaml' + - name: create service + ansible.builtin.copy: + dest: '{{ service.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + apiVersion: serving.knative.dev/v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + labels: + cloud.googleapis.com/location: '{{ SELF.gcp_region }}' + annotations: + run.googleapis.com/ingress: all + spec: + template: + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + containerPort: '{{ SELF.application_port }}' + env: [] + - name: apply service + ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet + args: + executable: /bin/bash + - name: touch policy + register: policy + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.policy.yaml' + - name: fill policy + ansible.builtin.copy: + dest: '{{ policy.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + bindings: + - members: + - allUsers + role: roles/run.invoker + - name: apply policy + ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + - name: describe service + register: service_description + ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + retailer.frontend.terminal~service.application#docker.image::ansible@kubernetes.cluster: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: create deployment + kubernetes.core.k8s: + wait: true + definition: + 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 }}' + - name: create service + kubernetes.core.k8s: + definition: + 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 + 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 }}' + retailer.frontend.terminal~service.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.frontend.terminal~service.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.frontend.terminal~service.application#zip.archive::ansible@gcp.appengine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: enable GCP AppEngine + ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + register: app_create_command + failed_when: + - "'Created' not in app_create_command.stderr" + - "'already contains' not in app_create_command.stderr" + - name: create working directory + register: directory + ansible.builtin.tempfile: + state: directory + - name: extract deployment artifact in working directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ directory.path }}' + - name: create specification + ansible.builtin.copy: + dest: '{{ directory.path }}/app.yaml' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + instance_class: F1 + env_variables: {} + - name: create app + ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet + args: + executable: /bin/bash + - name: browse app + register: browse_app + ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ browse_app.stdout[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet + args: + executable: /bin/bash + retailer.frontend.terminal~software.application#apt.package::ansible@*->remote.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.frontend.terminal~software.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.frontend.terminal~software.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.frontend.terminal~service.application#docker.image::terraform@docker.engine->local.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.frontend.terminal~service.application#docker.image::terraform@docker.engine->remote.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.frontend.terminal~service.application#docker.image::terraform@gcp.cloudrun: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' + resource: + google_cloud_run_v2_service: + application: + - ingress: INGRESS_TRAFFIC_ALL + location: '{{ SELF.gcp_region }}' + name: '{{ SELF.application_name }}' + template: + - containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + container_port: '{{ SELF.application_port }}' + env: [] + google_cloud_run_service_iam_binding: + application: + - location: '{{ SELF.gcp_region }}' + members: + - allUsers + role: roles/run.invoker + service: '{{ SELF.application_name }}' + retailer.frontend.terminal~service.application#docker.image::terraform@kubernetes.cluster: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_deployment_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - selector: + - match_labels: + app: '{{ SELF.application_name }}' + template: + - metadata: + - labels: + app: '{{ SELF.application_name }}' + spec: + - container: + - env: [] + image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + port: + - container_port: '{{ SELF.application_port }}' + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - port: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + target_port: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + retailer.frontend.terminal~service.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.frontend.terminal + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.frontend.terminal {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.frontend.terminal -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.frontend.terminal.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.frontend.terminal.sh + - sudo bash /tmp/configure-retailer.frontend.terminal.sh + - sudo bash /tmp/start-retailer.frontend.terminal.sh + - inline: + - sudo bash /tmp/stop-retailer.frontend.terminal.sh + - sudo bash /tmp/delete-retailer.frontend.terminal.sh + when: destroy + retailer.frontend.terminal~service.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.frontend.terminal + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.frontend.terminal {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.frontend.terminal -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.frontend.terminal.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.frontend.terminal.sh + - sudo bash /tmp/configure-retailer.frontend.terminal.sh + - sudo bash /tmp/start-retailer.frontend.terminal.sh + - inline: + - sudo bash /tmp/stop-retailer.frontend.terminal.sh + - sudo bash /tmp/delete-retailer.frontend.terminal.sh + when: destroy + retailer.frontend.terminal~service.application#zip.archive::terraform@gcp.appengine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' + resource: + google_app_engine_standard_app_version: + app: + - delete_service_on_destroy: true + deployment: + - zip: + - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} + entrypoint: + - shell: '{{ SELF._management_start }}' + env_variables: {} + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + service_account: ${google_service_account.custom_service_account.email} + version_id: v1 + google_project_iam_member: + gae_api: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/compute.networkUser + storage_viewer: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/storage.objectViewer + google_service_account: + custom_service_account: + - account_id: '{{ SELF.application_name }}-account' + display_name: Custom Service Account + google_storage_bucket: + bucket: + - location: EU + name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' + google_storage_bucket_object: + object: + - bucket: ${google_storage_bucket.bucket.name} + name: object.zip + source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + retailer.frontend.terminal~software.application#apt.archive::terraform@*->remote.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.frontend.terminal {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-retailer.frontend.terminal.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.frontend.terminal.sh + - sudo bash /tmp/configure-retailer.frontend.terminal.sh + - sudo bash /tmp/start-retailer.frontend.terminal.sh + - inline: + - sudo bash /tmp/stop-retailer.frontend.terminal.sh + - sudo bash /tmp/delete-retailer.frontend.terminal.sh + when: destroy + retailer.frontend.terminal~software.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.frontend.terminal + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.frontend.terminal {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.frontend.terminal -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.frontend.terminal.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.frontend.terminal.sh + - sudo bash /tmp/configure-retailer.frontend.terminal.sh + - sudo bash /tmp/start-retailer.frontend.terminal.sh + - inline: + - sudo bash /tmp/stop-retailer.frontend.terminal.sh + - sudo bash /tmp/delete-retailer.frontend.terminal.sh + when: destroy + retailer.frontend.terminal~software.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.frontend.terminal + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.frontend.terminal {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.frontend.terminal -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.frontend.terminal.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.frontend.terminal.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.frontend.terminal.sh + - sudo bash /tmp/configure-retailer.frontend.terminal.sh + - sudo bash /tmp/start-retailer.frontend.terminal.sh + - inline: + - sudo bash /tmp/stop-retailer.frontend.terminal.sh + - sudo bash /tmp/delete-retailer.frontend.terminal.sh + when: destroy + retailer.frontend.terminal~service.application#docker.image::kubernetes@kubernetes.cluster: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: 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 }} 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 + retailer.frontend.terminal~service.application#docker.image::compose@docker.engine->local.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 + retailer.frontend.terminal~service.application#docker.image::compose@docker.engine->remote.machine: + derived_from: retailer.frontend.terminal + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 }}' + retailer.service.gateway~service.application#docker.image::ansible@docker.engine->local.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + retailer.service.gateway~service.application#docker.image::ansible@docker.engine->remote.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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 }}' + retailer.service.gateway~service.application#docker.image::ansible@gcp.cloudrun: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: touch service + register: service + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.service.yaml' + - name: create service + ansible.builtin.copy: + dest: '{{ service.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + apiVersion: serving.knative.dev/v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + labels: + cloud.googleapis.com/location: '{{ SELF.gcp_region }}' + annotations: + run.googleapis.com/ingress: all + spec: + template: + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + containerPort: '{{ SELF.application_port }}' + env: [] + - name: apply service + ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet + args: + executable: /bin/bash + - name: touch policy + register: policy + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.policy.yaml' + - name: fill policy + ansible.builtin.copy: + dest: '{{ policy.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + bindings: + - members: + - allUsers + role: roles/run.invoker + - name: apply policy + ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + - name: describe service + register: service_description + ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + retailer.service.gateway~service.application#docker.image::ansible@kubernetes.cluster: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: create deployment + kubernetes.core.k8s: + wait: true + definition: + 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 }}' + - name: create service + kubernetes.core.k8s: + definition: + 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 + 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 }}' + retailer.service.gateway~service.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.gateway~service.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.gateway~service.application#zip.archive::ansible@gcp.appengine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: enable GCP AppEngine + ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + register: app_create_command + failed_when: + - "'Created' not in app_create_command.stderr" + - "'already contains' not in app_create_command.stderr" + - name: create working directory + register: directory + ansible.builtin.tempfile: + state: directory + - name: extract deployment artifact in working directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ directory.path }}' + - name: create specification + ansible.builtin.copy: + dest: '{{ directory.path }}/app.yaml' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + instance_class: F1 + env_variables: {} + - name: create app + ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet + args: + executable: /bin/bash + - name: browse app + register: browse_app + ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ browse_app.stdout[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet + args: + executable: /bin/bash + retailer.service.gateway~software.application#apt.package::ansible@*->remote.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.gateway~software.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.gateway~software.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.gateway~service.application#docker.image::terraform@docker.engine->local.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.gateway~service.application#docker.image::terraform@docker.engine->remote.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.gateway~service.application#docker.image::terraform@gcp.cloudrun: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' + resource: + google_cloud_run_v2_service: + application: + - ingress: INGRESS_TRAFFIC_ALL + location: '{{ SELF.gcp_region }}' + name: '{{ SELF.application_name }}' + template: + - containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + container_port: '{{ SELF.application_port }}' + env: [] + google_cloud_run_service_iam_binding: + application: + - location: '{{ SELF.gcp_region }}' + members: + - allUsers + role: roles/run.invoker + service: '{{ SELF.application_name }}' + retailer.service.gateway~service.application#docker.image::terraform@kubernetes.cluster: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_deployment_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - selector: + - match_labels: + app: '{{ SELF.application_name }}' + template: + - metadata: + - labels: + app: '{{ SELF.application_name }}' + spec: + - container: + - env: [] + image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + port: + - container_port: '{{ SELF.application_port }}' + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - port: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + target_port: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + retailer.service.gateway~service.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.gateway + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.gateway {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.gateway -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.gateway.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.gateway.sh + - sudo bash /tmp/configure-retailer.service.gateway.sh + - sudo bash /tmp/start-retailer.service.gateway.sh + - inline: + - sudo bash /tmp/stop-retailer.service.gateway.sh + - sudo bash /tmp/delete-retailer.service.gateway.sh + when: destroy + retailer.service.gateway~service.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.gateway + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.gateway {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.gateway -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.gateway.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.gateway.sh + - sudo bash /tmp/configure-retailer.service.gateway.sh + - sudo bash /tmp/start-retailer.service.gateway.sh + - inline: + - sudo bash /tmp/stop-retailer.service.gateway.sh + - sudo bash /tmp/delete-retailer.service.gateway.sh + when: destroy + retailer.service.gateway~service.application#zip.archive::terraform@gcp.appengine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' + resource: + google_app_engine_standard_app_version: + app: + - delete_service_on_destroy: true + deployment: + - zip: + - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} + entrypoint: + - shell: '{{ SELF._management_start }}' + env_variables: {} + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + service_account: ${google_service_account.custom_service_account.email} + version_id: v1 + google_project_iam_member: + gae_api: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/compute.networkUser + storage_viewer: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/storage.objectViewer + google_service_account: + custom_service_account: + - account_id: '{{ SELF.application_name }}-account' + display_name: Custom Service Account + google_storage_bucket: + bucket: + - location: EU + name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' + google_storage_bucket_object: + object: + - bucket: ${google_storage_bucket.bucket.name} + name: object.zip + source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + retailer.service.gateway~software.application#apt.archive::terraform@*->remote.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.gateway {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-retailer.service.gateway.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.gateway.sh + - sudo bash /tmp/configure-retailer.service.gateway.sh + - sudo bash /tmp/start-retailer.service.gateway.sh + - inline: + - sudo bash /tmp/stop-retailer.service.gateway.sh + - sudo bash /tmp/delete-retailer.service.gateway.sh + when: destroy + retailer.service.gateway~software.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.gateway + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.gateway {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.gateway -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.gateway.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.gateway.sh + - sudo bash /tmp/configure-retailer.service.gateway.sh + - sudo bash /tmp/start-retailer.service.gateway.sh + - inline: + - sudo bash /tmp/stop-retailer.service.gateway.sh + - sudo bash /tmp/delete-retailer.service.gateway.sh + when: destroy + retailer.service.gateway~software.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.gateway + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.gateway {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.gateway -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.gateway.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.gateway.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.gateway.sh + - sudo bash /tmp/configure-retailer.service.gateway.sh + - sudo bash /tmp/start-retailer.service.gateway.sh + - inline: + - sudo bash /tmp/stop-retailer.service.gateway.sh + - sudo bash /tmp/delete-retailer.service.gateway.sh + when: destroy + retailer.service.gateway~service.application#docker.image::kubernetes@kubernetes.cluster: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: 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 }} 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 + retailer.service.gateway~service.application#docker.image::compose@docker.engine->local.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 + retailer.service.gateway~service.application#docker.image::compose@docker.engine->remote.machine: + derived_from: retailer.service.gateway + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 }}' + retailer.service.core~service.application#docker.image::ansible@docker.engine->local.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + retailer.service.core~service.application#docker.image::ansible@docker.engine->remote.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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 }}' + retailer.service.core~service.application#docker.image::ansible@gcp.cloudrun: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: touch service + register: service + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.service.yaml' + - name: create service + ansible.builtin.copy: + dest: '{{ service.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + apiVersion: serving.knative.dev/v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + labels: + cloud.googleapis.com/location: '{{ SELF.gcp_region }}' + annotations: + run.googleapis.com/ingress: all + spec: + template: + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + containerPort: '{{ SELF.application_port }}' + env: [] + - name: apply service + ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet + args: + executable: /bin/bash + - name: touch policy + register: policy + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.policy.yaml' + - name: fill policy + ansible.builtin.copy: + dest: '{{ policy.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + bindings: + - members: + - allUsers + role: roles/run.invoker + - name: apply policy + ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + - name: describe service + register: service_description + ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + retailer.service.core~service.application#docker.image::ansible@kubernetes.cluster: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: create deployment + kubernetes.core.k8s: + wait: true + definition: + 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 }}' + - name: create service + kubernetes.core.k8s: + definition: + 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 + 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 }}' + retailer.service.core~service.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.core~service.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.core~service.application#zip.archive::ansible@gcp.appengine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: enable GCP AppEngine + ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + register: app_create_command + failed_when: + - "'Created' not in app_create_command.stderr" + - "'already contains' not in app_create_command.stderr" + - name: create working directory + register: directory + ansible.builtin.tempfile: + state: directory + - name: extract deployment artifact in working directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ directory.path }}' + - name: create specification + ansible.builtin.copy: + dest: '{{ directory.path }}/app.yaml' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + instance_class: F1 + env_variables: {} + - name: create app + ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet + args: + executable: /bin/bash + - name: browse app + register: browse_app + ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ browse_app.stdout[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet + args: + executable: /bin/bash + retailer.service.core~software.application#apt.package::ansible@*->remote.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.core~software.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.core~software.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.core~service.application#docker.image::terraform@docker.engine->local.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.core~service.application#docker.image::terraform@docker.engine->remote.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.core~service.application#docker.image::terraform@gcp.cloudrun: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' + resource: + google_cloud_run_v2_service: + application: + - ingress: INGRESS_TRAFFIC_ALL + location: '{{ SELF.gcp_region }}' + name: '{{ SELF.application_name }}' + template: + - containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + container_port: '{{ SELF.application_port }}' + env: [] + google_cloud_run_service_iam_binding: + application: + - location: '{{ SELF.gcp_region }}' + members: + - allUsers + role: roles/run.invoker + service: '{{ SELF.application_name }}' + retailer.service.core~service.application#docker.image::terraform@kubernetes.cluster: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_deployment_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - selector: + - match_labels: + app: '{{ SELF.application_name }}' + template: + - metadata: + - labels: + app: '{{ SELF.application_name }}' + spec: + - container: + - env: [] + image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + port: + - container_port: '{{ SELF.application_port }}' + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - port: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + target_port: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + retailer.service.core~service.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.core + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.core {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.core -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.core.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.core.sh + - sudo bash /tmp/configure-retailer.service.core.sh + - sudo bash /tmp/start-retailer.service.core.sh + - inline: + - sudo bash /tmp/stop-retailer.service.core.sh + - sudo bash /tmp/delete-retailer.service.core.sh + when: destroy + retailer.service.core~service.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.core + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.core {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.core -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.core.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.core.sh + - sudo bash /tmp/configure-retailer.service.core.sh + - sudo bash /tmp/start-retailer.service.core.sh + - inline: + - sudo bash /tmp/stop-retailer.service.core.sh + - sudo bash /tmp/delete-retailer.service.core.sh + when: destroy + retailer.service.core~service.application#zip.archive::terraform@gcp.appengine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' + resource: + google_app_engine_standard_app_version: + app: + - delete_service_on_destroy: true + deployment: + - zip: + - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} + entrypoint: + - shell: '{{ SELF._management_start }}' + env_variables: {} + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + service_account: ${google_service_account.custom_service_account.email} + version_id: v1 + google_project_iam_member: + gae_api: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/compute.networkUser + storage_viewer: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/storage.objectViewer + google_service_account: + custom_service_account: + - account_id: '{{ SELF.application_name }}-account' + display_name: Custom Service Account + google_storage_bucket: + bucket: + - location: EU + name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' + google_storage_bucket_object: + object: + - bucket: ${google_storage_bucket.bucket.name} + name: object.zip + source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + retailer.service.core~software.application#apt.archive::terraform@*->remote.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.core {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-retailer.service.core.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.core.sh + - sudo bash /tmp/configure-retailer.service.core.sh + - sudo bash /tmp/start-retailer.service.core.sh + - inline: + - sudo bash /tmp/stop-retailer.service.core.sh + - sudo bash /tmp/delete-retailer.service.core.sh + when: destroy + retailer.service.core~software.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.core + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.core {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.core -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.core.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.core.sh + - sudo bash /tmp/configure-retailer.service.core.sh + - sudo bash /tmp/start-retailer.service.core.sh + - inline: + - sudo bash /tmp/stop-retailer.service.core.sh + - sudo bash /tmp/delete-retailer.service.core.sh + when: destroy + retailer.service.core~software.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.core + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.core {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.core -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.core.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.core.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.core.sh + - sudo bash /tmp/configure-retailer.service.core.sh + - sudo bash /tmp/start-retailer.service.core.sh + - inline: + - sudo bash /tmp/stop-retailer.service.core.sh + - sudo bash /tmp/delete-retailer.service.core.sh + when: destroy + retailer.service.core~service.application#docker.image::kubernetes@kubernetes.cluster: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: 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 }} 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 + retailer.service.core~service.application#docker.image::compose@docker.engine->local.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 + retailer.service.core~service.application#docker.image::compose@docker.engine->remote.machine: + derived_from: retailer.service.core + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 }}' + retailer.service.jobs~service.application#docker.image::ansible@docker.engine->local.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + retailer.service.jobs~service.application#docker.image::ansible@docker.engine->remote.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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 }}' + retailer.service.jobs~service.application#docker.image::ansible@gcp.cloudrun: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: touch service + register: service + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.service.yaml' + - name: create service + ansible.builtin.copy: + dest: '{{ service.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + apiVersion: serving.knative.dev/v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + labels: + cloud.googleapis.com/location: '{{ SELF.gcp_region }}' + annotations: + run.googleapis.com/ingress: all + spec: + template: + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + containerPort: '{{ SELF.application_port }}' + env: [] + - name: apply service + ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet + args: + executable: /bin/bash + - name: touch policy + register: policy + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.policy.yaml' + - name: fill policy + ansible.builtin.copy: + dest: '{{ policy.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + bindings: + - members: + - allUsers + role: roles/run.invoker + - name: apply policy + ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + - name: describe service + register: service_description + ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + retailer.service.jobs~service.application#docker.image::ansible@kubernetes.cluster: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: create deployment + kubernetes.core.k8s: + wait: true + definition: + 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 }}' + - name: create service + kubernetes.core.k8s: + definition: + 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 + 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 }}' + retailer.service.jobs~service.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.jobs~service.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.jobs~service.application#zip.archive::ansible@gcp.appengine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: enable GCP AppEngine + ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + register: app_create_command + failed_when: + - "'Created' not in app_create_command.stderr" + - "'already contains' not in app_create_command.stderr" + - name: create working directory + register: directory + ansible.builtin.tempfile: + state: directory + - name: extract deployment artifact in working directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ directory.path }}' + - name: create specification + ansible.builtin.copy: + dest: '{{ directory.path }}/app.yaml' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + instance_class: F1 + env_variables: {} + - name: create app + ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet + args: + executable: /bin/bash + - name: browse app + register: browse_app + ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ browse_app.stdout[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet + args: + executable: /bin/bash + retailer.service.jobs~software.application#apt.package::ansible@*->remote.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.jobs~software.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.jobs~software.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.jobs~service.application#docker.image::terraform@docker.engine->local.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.jobs~service.application#docker.image::terraform@docker.engine->remote.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.jobs~service.application#docker.image::terraform@gcp.cloudrun: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' + resource: + google_cloud_run_v2_service: + application: + - ingress: INGRESS_TRAFFIC_ALL + location: '{{ SELF.gcp_region }}' + name: '{{ SELF.application_name }}' + template: + - containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + container_port: '{{ SELF.application_port }}' + env: [] + google_cloud_run_service_iam_binding: + application: + - location: '{{ SELF.gcp_region }}' + members: + - allUsers + role: roles/run.invoker + service: '{{ SELF.application_name }}' + retailer.service.jobs~service.application#docker.image::terraform@kubernetes.cluster: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_deployment_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - selector: + - match_labels: + app: '{{ SELF.application_name }}' + template: + - metadata: + - labels: + app: '{{ SELF.application_name }}' + spec: + - container: + - env: [] + image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + port: + - container_port: '{{ SELF.application_port }}' + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - port: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + target_port: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + retailer.service.jobs~service.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.jobs + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.jobs {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.jobs -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.jobs.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.jobs.sh + - sudo bash /tmp/configure-retailer.service.jobs.sh + - sudo bash /tmp/start-retailer.service.jobs.sh + - inline: + - sudo bash /tmp/stop-retailer.service.jobs.sh + - sudo bash /tmp/delete-retailer.service.jobs.sh + when: destroy + retailer.service.jobs~service.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.jobs + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.jobs {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.jobs -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.jobs.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.jobs.sh + - sudo bash /tmp/configure-retailer.service.jobs.sh + - sudo bash /tmp/start-retailer.service.jobs.sh + - inline: + - sudo bash /tmp/stop-retailer.service.jobs.sh + - sudo bash /tmp/delete-retailer.service.jobs.sh + when: destroy + retailer.service.jobs~service.application#zip.archive::terraform@gcp.appengine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' + resource: + google_app_engine_standard_app_version: + app: + - delete_service_on_destroy: true + deployment: + - zip: + - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} + entrypoint: + - shell: '{{ SELF._management_start }}' + env_variables: {} + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + service_account: ${google_service_account.custom_service_account.email} + version_id: v1 + google_project_iam_member: + gae_api: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/compute.networkUser + storage_viewer: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/storage.objectViewer + google_service_account: + custom_service_account: + - account_id: '{{ SELF.application_name }}-account' + display_name: Custom Service Account + google_storage_bucket: + bucket: + - location: EU + name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' + google_storage_bucket_object: + object: + - bucket: ${google_storage_bucket.bucket.name} + name: object.zip + source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + retailer.service.jobs~software.application#apt.archive::terraform@*->remote.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.jobs {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-retailer.service.jobs.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.jobs.sh + - sudo bash /tmp/configure-retailer.service.jobs.sh + - sudo bash /tmp/start-retailer.service.jobs.sh + - inline: + - sudo bash /tmp/stop-retailer.service.jobs.sh + - sudo bash /tmp/delete-retailer.service.jobs.sh + when: destroy + retailer.service.jobs~software.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.jobs + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.jobs {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.jobs -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.jobs.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.jobs.sh + - sudo bash /tmp/configure-retailer.service.jobs.sh + - sudo bash /tmp/start-retailer.service.jobs.sh + - inline: + - sudo bash /tmp/stop-retailer.service.jobs.sh + - sudo bash /tmp/delete-retailer.service.jobs.sh + when: destroy + retailer.service.jobs~software.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.jobs + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.jobs {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.jobs -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.jobs.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.jobs.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.jobs.sh + - sudo bash /tmp/configure-retailer.service.jobs.sh + - sudo bash /tmp/start-retailer.service.jobs.sh + - inline: + - sudo bash /tmp/stop-retailer.service.jobs.sh + - sudo bash /tmp/delete-retailer.service.jobs.sh + when: destroy + retailer.service.jobs~service.application#docker.image::kubernetes@kubernetes.cluster: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: 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 }} 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 + retailer.service.jobs~service.application#docker.image::compose@docker.engine->local.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 + retailer.service.jobs~service.application#docker.image::compose@docker.engine->remote.machine: + derived_from: retailer.service.jobs + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 }}' + retailer.service.stores~service.application#docker.image::ansible@docker.engine->local.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + retailer.service.stores~service.application#docker.image::ansible@docker.engine->remote.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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 }}' + retailer.service.stores~service.application#docker.image::ansible@gcp.cloudrun: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: touch service + register: service + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.service.yaml' + - name: create service + ansible.builtin.copy: + dest: '{{ service.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + apiVersion: serving.knative.dev/v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + labels: + cloud.googleapis.com/location: '{{ SELF.gcp_region }}' + annotations: + run.googleapis.com/ingress: all + spec: + template: + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + containerPort: '{{ SELF.application_port }}' + env: [] + - name: apply service + ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet + args: + executable: /bin/bash + - name: touch policy + register: policy + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.policy.yaml' + - name: fill policy + ansible.builtin.copy: + dest: '{{ policy.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + bindings: + - members: + - allUsers + role: roles/run.invoker + - name: apply policy + ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + - name: describe service + register: service_description + ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + retailer.service.stores~service.application#docker.image::ansible@kubernetes.cluster: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: create deployment + kubernetes.core.k8s: + wait: true + definition: + 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 }}' + - name: create service + kubernetes.core.k8s: + definition: + 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 + 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 }}' + retailer.service.stores~service.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.stores~service.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.stores~service.application#zip.archive::ansible@gcp.appengine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: enable GCP AppEngine + ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + register: app_create_command + failed_when: + - "'Created' not in app_create_command.stderr" + - "'already contains' not in app_create_command.stderr" + - name: create working directory + register: directory + ansible.builtin.tempfile: + state: directory + - name: extract deployment artifact in working directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ directory.path }}' + - name: create specification + ansible.builtin.copy: + dest: '{{ directory.path }}/app.yaml' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + instance_class: F1 + env_variables: {} + - name: create app + ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet + args: + executable: /bin/bash + - name: browse app + register: browse_app + ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ browse_app.stdout[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet + args: + executable: /bin/bash + retailer.service.stores~software.application#apt.package::ansible@*->remote.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.stores~software.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.stores~software.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.stores~service.application#docker.image::terraform@docker.engine->local.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.stores~service.application#docker.image::terraform@docker.engine->remote.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.stores~service.application#docker.image::terraform@gcp.cloudrun: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' + resource: + google_cloud_run_v2_service: + application: + - ingress: INGRESS_TRAFFIC_ALL + location: '{{ SELF.gcp_region }}' + name: '{{ SELF.application_name }}' + template: + - containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + container_port: '{{ SELF.application_port }}' + env: [] + google_cloud_run_service_iam_binding: + application: + - location: '{{ SELF.gcp_region }}' + members: + - allUsers + role: roles/run.invoker + service: '{{ SELF.application_name }}' + retailer.service.stores~service.application#docker.image::terraform@kubernetes.cluster: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_deployment_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - selector: + - match_labels: + app: '{{ SELF.application_name }}' + template: + - metadata: + - labels: + app: '{{ SELF.application_name }}' + spec: + - container: + - env: [] + image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + port: + - container_port: '{{ SELF.application_port }}' + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - port: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + target_port: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + retailer.service.stores~service.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.stores + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.stores {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.stores -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.stores.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.stores.sh + - sudo bash /tmp/configure-retailer.service.stores.sh + - sudo bash /tmp/start-retailer.service.stores.sh + - inline: + - sudo bash /tmp/stop-retailer.service.stores.sh + - sudo bash /tmp/delete-retailer.service.stores.sh + when: destroy + retailer.service.stores~service.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.stores + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.stores {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.stores -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.stores.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.stores.sh + - sudo bash /tmp/configure-retailer.service.stores.sh + - sudo bash /tmp/start-retailer.service.stores.sh + - inline: + - sudo bash /tmp/stop-retailer.service.stores.sh + - sudo bash /tmp/delete-retailer.service.stores.sh + when: destroy + retailer.service.stores~service.application#zip.archive::terraform@gcp.appengine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' + resource: + google_app_engine_standard_app_version: + app: + - delete_service_on_destroy: true + deployment: + - zip: + - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} + entrypoint: + - shell: '{{ SELF._management_start }}' + env_variables: {} + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + service_account: ${google_service_account.custom_service_account.email} + version_id: v1 + google_project_iam_member: + gae_api: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/compute.networkUser + storage_viewer: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/storage.objectViewer + google_service_account: + custom_service_account: + - account_id: '{{ SELF.application_name }}-account' + display_name: Custom Service Account + google_storage_bucket: + bucket: + - location: EU + name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' + google_storage_bucket_object: + object: + - bucket: ${google_storage_bucket.bucket.name} + name: object.zip + source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + retailer.service.stores~software.application#apt.archive::terraform@*->remote.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.stores {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-retailer.service.stores.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.stores.sh + - sudo bash /tmp/configure-retailer.service.stores.sh + - sudo bash /tmp/start-retailer.service.stores.sh + - inline: + - sudo bash /tmp/stop-retailer.service.stores.sh + - sudo bash /tmp/delete-retailer.service.stores.sh + when: destroy + retailer.service.stores~software.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.stores + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.stores {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.stores -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.stores.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.stores.sh + - sudo bash /tmp/configure-retailer.service.stores.sh + - sudo bash /tmp/start-retailer.service.stores.sh + - inline: + - sudo bash /tmp/stop-retailer.service.stores.sh + - sudo bash /tmp/delete-retailer.service.stores.sh + when: destroy + retailer.service.stores~software.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.stores + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.stores {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.stores -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.stores.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.stores.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.stores.sh + - sudo bash /tmp/configure-retailer.service.stores.sh + - sudo bash /tmp/start-retailer.service.stores.sh + - inline: + - sudo bash /tmp/stop-retailer.service.stores.sh + - sudo bash /tmp/delete-retailer.service.stores.sh + when: destroy + retailer.service.stores~service.application#docker.image::kubernetes@kubernetes.cluster: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: 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 }} 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 + retailer.service.stores~service.application#docker.image::compose@docker.engine->local.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 + retailer.service.stores~service.application#docker.image::compose@docker.engine->remote.machine: + derived_from: retailer.service.stores + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 }}' + retailer.service.products~service.application#docker.image::ansible@docker.engine->local.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + retailer.service.products~service.application#docker.image::ansible@docker.engine->remote.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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 }}' + retailer.service.products~service.application#docker.image::ansible@gcp.cloudrun: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: touch service + register: service + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.service.yaml' + - name: create service + ansible.builtin.copy: + dest: '{{ service.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + apiVersion: serving.knative.dev/v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + labels: + cloud.googleapis.com/location: '{{ SELF.gcp_region }}' + annotations: + run.googleapis.com/ingress: all + spec: + template: + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + containerPort: '{{ SELF.application_port }}' + env: [] + - name: apply service + ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet + args: + executable: /bin/bash + - name: touch policy + register: policy + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.policy.yaml' + - name: fill policy + ansible.builtin.copy: + dest: '{{ policy.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + bindings: + - members: + - allUsers + role: roles/run.invoker + - name: apply policy + ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + - name: describe service + register: service_description + ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + retailer.service.products~service.application#docker.image::ansible@kubernetes.cluster: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: create deployment + kubernetes.core.k8s: + wait: true + definition: + 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 }}' + - name: create service + kubernetes.core.k8s: + definition: + 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 + 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 }}' + retailer.service.products~service.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.products~service.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.products~service.application#zip.archive::ansible@gcp.appengine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: enable GCP AppEngine + ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + register: app_create_command + failed_when: + - "'Created' not in app_create_command.stderr" + - "'already contains' not in app_create_command.stderr" + - name: create working directory + register: directory + ansible.builtin.tempfile: + state: directory + - name: extract deployment artifact in working directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ directory.path }}' + - name: create specification + ansible.builtin.copy: + dest: '{{ directory.path }}/app.yaml' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + instance_class: F1 + env_variables: {} + - name: create app + ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet + args: + executable: /bin/bash + - name: browse app + register: browse_app + ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ browse_app.stdout[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet + args: + executable: /bin/bash + retailer.service.products~software.application#apt.package::ansible@*->remote.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.products~software.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.products~software.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.products~service.application#docker.image::terraform@docker.engine->local.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.products~service.application#docker.image::terraform@docker.engine->remote.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.products~service.application#docker.image::terraform@gcp.cloudrun: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' + resource: + google_cloud_run_v2_service: + application: + - ingress: INGRESS_TRAFFIC_ALL + location: '{{ SELF.gcp_region }}' + name: '{{ SELF.application_name }}' + template: + - containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + container_port: '{{ SELF.application_port }}' + env: [] + google_cloud_run_service_iam_binding: + application: + - location: '{{ SELF.gcp_region }}' + members: + - allUsers + role: roles/run.invoker + service: '{{ SELF.application_name }}' + retailer.service.products~service.application#docker.image::terraform@kubernetes.cluster: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_deployment_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - selector: + - match_labels: + app: '{{ SELF.application_name }}' + template: + - metadata: + - labels: + app: '{{ SELF.application_name }}' + spec: + - container: + - env: [] + image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + port: + - container_port: '{{ SELF.application_port }}' + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - port: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + target_port: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + retailer.service.products~service.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.products + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.products {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.products -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.products.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.products.sh + - sudo bash /tmp/configure-retailer.service.products.sh + - sudo bash /tmp/start-retailer.service.products.sh + - inline: + - sudo bash /tmp/stop-retailer.service.products.sh + - sudo bash /tmp/delete-retailer.service.products.sh + when: destroy + retailer.service.products~service.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.products + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.products {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.products -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.products.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.products.sh + - sudo bash /tmp/configure-retailer.service.products.sh + - sudo bash /tmp/start-retailer.service.products.sh + - inline: + - sudo bash /tmp/stop-retailer.service.products.sh + - sudo bash /tmp/delete-retailer.service.products.sh + when: destroy + retailer.service.products~service.application#zip.archive::terraform@gcp.appengine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' + resource: + google_app_engine_standard_app_version: + app: + - delete_service_on_destroy: true + deployment: + - zip: + - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} + entrypoint: + - shell: '{{ SELF._management_start }}' + env_variables: {} + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + service_account: ${google_service_account.custom_service_account.email} + version_id: v1 + google_project_iam_member: + gae_api: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/compute.networkUser + storage_viewer: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/storage.objectViewer + google_service_account: + custom_service_account: + - account_id: '{{ SELF.application_name }}-account' + display_name: Custom Service Account + google_storage_bucket: + bucket: + - location: EU + name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' + google_storage_bucket_object: + object: + - bucket: ${google_storage_bucket.bucket.name} + name: object.zip + source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + retailer.service.products~software.application#apt.archive::terraform@*->remote.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.products {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-retailer.service.products.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.products.sh + - sudo bash /tmp/configure-retailer.service.products.sh + - sudo bash /tmp/start-retailer.service.products.sh + - inline: + - sudo bash /tmp/stop-retailer.service.products.sh + - sudo bash /tmp/delete-retailer.service.products.sh + when: destroy + retailer.service.products~software.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.products + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.products {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.products -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.products.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.products.sh + - sudo bash /tmp/configure-retailer.service.products.sh + - sudo bash /tmp/start-retailer.service.products.sh + - inline: + - sudo bash /tmp/stop-retailer.service.products.sh + - sudo bash /tmp/delete-retailer.service.products.sh + when: destroy + retailer.service.products~software.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.products + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.products {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.products -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.products.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.products.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.products.sh + - sudo bash /tmp/configure-retailer.service.products.sh + - sudo bash /tmp/start-retailer.service.products.sh + - inline: + - sudo bash /tmp/stop-retailer.service.products.sh + - sudo bash /tmp/delete-retailer.service.products.sh + when: destroy + retailer.service.products~service.application#docker.image::kubernetes@kubernetes.cluster: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: 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 }} 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 + retailer.service.products~service.application#docker.image::compose@docker.engine->local.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 + retailer.service.products~service.application#docker.image::compose@docker.engine->remote.machine: + derived_from: retailer.service.products + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 }}' + retailer.service.stocks~service.application#docker.image::ansible@docker.engine->local.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + retailer.service.stocks~service.application#docker.image::ansible@docker.engine->remote.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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 }}' + retailer.service.stocks~service.application#docker.image::ansible@gcp.cloudrun: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: touch service + register: service + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.service.yaml' + - name: create service + ansible.builtin.copy: + dest: '{{ service.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + apiVersion: serving.knative.dev/v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + labels: + cloud.googleapis.com/location: '{{ SELF.gcp_region }}' + annotations: + run.googleapis.com/ingress: all + spec: + template: + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + containerPort: '{{ SELF.application_port }}' + env: [] + - name: apply service + ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet + args: + executable: /bin/bash + - name: touch policy + register: policy + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.policy.yaml' + - name: fill policy + ansible.builtin.copy: + dest: '{{ policy.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + bindings: + - members: + - allUsers + role: roles/run.invoker + - name: apply policy + ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + - name: describe service + register: service_description + ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + retailer.service.stocks~service.application#docker.image::ansible@kubernetes.cluster: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: create deployment + kubernetes.core.k8s: + wait: true + definition: + 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 }}' + - name: create service + kubernetes.core.k8s: + definition: + 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 + 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 }}' + retailer.service.stocks~service.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.stocks~service.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.stocks~service.application#zip.archive::ansible@gcp.appengine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: enable GCP AppEngine + ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + register: app_create_command + failed_when: + - "'Created' not in app_create_command.stderr" + - "'already contains' not in app_create_command.stderr" + - name: create working directory + register: directory + ansible.builtin.tempfile: + state: directory + - name: extract deployment artifact in working directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ directory.path }}' + - name: create specification + ansible.builtin.copy: + dest: '{{ directory.path }}/app.yaml' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + instance_class: F1 + env_variables: {} + - name: create app + ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet + args: + executable: /bin/bash + - name: browse app + register: browse_app + ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ browse_app.stdout[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet + args: + executable: /bin/bash + retailer.service.stocks~software.application#apt.package::ansible@*->remote.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.stocks~software.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.stocks~software.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.stocks~service.application#docker.image::terraform@docker.engine->local.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.stocks~service.application#docker.image::terraform@docker.engine->remote.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.stocks~service.application#docker.image::terraform@gcp.cloudrun: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' + resource: + google_cloud_run_v2_service: + application: + - ingress: INGRESS_TRAFFIC_ALL + location: '{{ SELF.gcp_region }}' + name: '{{ SELF.application_name }}' + template: + - containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + container_port: '{{ SELF.application_port }}' + env: [] + google_cloud_run_service_iam_binding: + application: + - location: '{{ SELF.gcp_region }}' + members: + - allUsers + role: roles/run.invoker + service: '{{ SELF.application_name }}' + retailer.service.stocks~service.application#docker.image::terraform@kubernetes.cluster: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_deployment_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - selector: + - match_labels: + app: '{{ SELF.application_name }}' + template: + - metadata: + - labels: + app: '{{ SELF.application_name }}' + spec: + - container: + - env: [] + image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + port: + - container_port: '{{ SELF.application_port }}' + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - port: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + target_port: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + retailer.service.stocks~service.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.stocks + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.stocks {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.stocks -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.stocks.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.stocks.sh + - sudo bash /tmp/configure-retailer.service.stocks.sh + - sudo bash /tmp/start-retailer.service.stocks.sh + - inline: + - sudo bash /tmp/stop-retailer.service.stocks.sh + - sudo bash /tmp/delete-retailer.service.stocks.sh + when: destroy + retailer.service.stocks~service.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.stocks + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.stocks {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.stocks -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.stocks.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.stocks.sh + - sudo bash /tmp/configure-retailer.service.stocks.sh + - sudo bash /tmp/start-retailer.service.stocks.sh + - inline: + - sudo bash /tmp/stop-retailer.service.stocks.sh + - sudo bash /tmp/delete-retailer.service.stocks.sh + when: destroy + retailer.service.stocks~service.application#zip.archive::terraform@gcp.appengine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' + resource: + google_app_engine_standard_app_version: + app: + - delete_service_on_destroy: true + deployment: + - zip: + - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} + entrypoint: + - shell: '{{ SELF._management_start }}' + env_variables: {} + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + service_account: ${google_service_account.custom_service_account.email} + version_id: v1 + google_project_iam_member: + gae_api: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/compute.networkUser + storage_viewer: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/storage.objectViewer + google_service_account: + custom_service_account: + - account_id: '{{ SELF.application_name }}-account' + display_name: Custom Service Account + google_storage_bucket: + bucket: + - location: EU + name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' + google_storage_bucket_object: + object: + - bucket: ${google_storage_bucket.bucket.name} + name: object.zip + source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + retailer.service.stocks~software.application#apt.archive::terraform@*->remote.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.stocks {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-retailer.service.stocks.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.stocks.sh + - sudo bash /tmp/configure-retailer.service.stocks.sh + - sudo bash /tmp/start-retailer.service.stocks.sh + - inline: + - sudo bash /tmp/stop-retailer.service.stocks.sh + - sudo bash /tmp/delete-retailer.service.stocks.sh + when: destroy + retailer.service.stocks~software.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.stocks + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.stocks {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.stocks -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.stocks.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.stocks.sh + - sudo bash /tmp/configure-retailer.service.stocks.sh + - sudo bash /tmp/start-retailer.service.stocks.sh + - inline: + - sudo bash /tmp/stop-retailer.service.stocks.sh + - sudo bash /tmp/delete-retailer.service.stocks.sh + when: destroy + retailer.service.stocks~software.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.stocks + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.stocks {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.stocks -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.stocks.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.stocks.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.stocks.sh + - sudo bash /tmp/configure-retailer.service.stocks.sh + - sudo bash /tmp/start-retailer.service.stocks.sh + - inline: + - sudo bash /tmp/stop-retailer.service.stocks.sh + - sudo bash /tmp/delete-retailer.service.stocks.sh + when: destroy + retailer.service.stocks~service.application#docker.image::kubernetes@kubernetes.cluster: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: 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 }} 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 + retailer.service.stocks~service.application#docker.image::compose@docker.engine->local.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 + retailer.service.stocks~service.application#docker.image::compose@docker.engine->remote.machine: + derived_from: retailer.service.stocks + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 }}' + retailer.service.orders~service.application#docker.image::ansible@docker.engine->local.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + retailer.service.orders~service.application#docker.image::ansible@docker.engine->remote.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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 }}' + retailer.service.orders~service.application#docker.image::ansible@gcp.cloudrun: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: touch service + register: service + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.service.yaml' + - name: create service + ansible.builtin.copy: + dest: '{{ service.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + apiVersion: serving.knative.dev/v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + labels: + cloud.googleapis.com/location: '{{ SELF.gcp_region }}' + annotations: + run.googleapis.com/ingress: all + spec: + template: + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + containerPort: '{{ SELF.application_port }}' + env: [] + - name: apply service + ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet + args: + executable: /bin/bash + - name: touch policy + register: policy + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.policy.yaml' + - name: fill policy + ansible.builtin.copy: + dest: '{{ policy.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + bindings: + - members: + - allUsers + role: roles/run.invoker + - name: apply policy + ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + - name: describe service + register: service_description + ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + retailer.service.orders~service.application#docker.image::ansible@kubernetes.cluster: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: create deployment + kubernetes.core.k8s: + wait: true + definition: + 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 }}' + - name: create service + kubernetes.core.k8s: + definition: + 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 + 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 }}' + retailer.service.orders~service.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.orders~service.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.orders~service.application#zip.archive::ansible@gcp.appengine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: enable GCP AppEngine + ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + register: app_create_command + failed_when: + - "'Created' not in app_create_command.stderr" + - "'already contains' not in app_create_command.stderr" + - name: create working directory + register: directory + ansible.builtin.tempfile: + state: directory + - name: extract deployment artifact in working directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ directory.path }}' + - name: create specification + ansible.builtin.copy: + dest: '{{ directory.path }}/app.yaml' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + instance_class: F1 + env_variables: {} + - name: create app + ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet + args: + executable: /bin/bash + - name: browse app + register: browse_app + ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ browse_app.stdout[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet + args: + executable: /bin/bash + retailer.service.orders~software.application#apt.package::ansible@*->remote.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.orders~software.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.orders~software.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.orders~service.application#docker.image::terraform@docker.engine->local.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.orders~service.application#docker.image::terraform@docker.engine->remote.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.orders~service.application#docker.image::terraform@gcp.cloudrun: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' + resource: + google_cloud_run_v2_service: + application: + - ingress: INGRESS_TRAFFIC_ALL + location: '{{ SELF.gcp_region }}' + name: '{{ SELF.application_name }}' + template: + - containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + container_port: '{{ SELF.application_port }}' + env: [] + google_cloud_run_service_iam_binding: + application: + - location: '{{ SELF.gcp_region }}' + members: + - allUsers + role: roles/run.invoker + service: '{{ SELF.application_name }}' + retailer.service.orders~service.application#docker.image::terraform@kubernetes.cluster: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_deployment_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - selector: + - match_labels: + app: '{{ SELF.application_name }}' + template: + - metadata: + - labels: + app: '{{ SELF.application_name }}' + spec: + - container: + - env: [] + image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + port: + - container_port: '{{ SELF.application_port }}' + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - port: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + target_port: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + retailer.service.orders~service.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.orders + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.orders {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.orders -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.orders.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.orders.sh + - sudo bash /tmp/configure-retailer.service.orders.sh + - sudo bash /tmp/start-retailer.service.orders.sh + - inline: + - sudo bash /tmp/stop-retailer.service.orders.sh + - sudo bash /tmp/delete-retailer.service.orders.sh + when: destroy + retailer.service.orders~service.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.orders + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.orders {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.orders -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.orders.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.orders.sh + - sudo bash /tmp/configure-retailer.service.orders.sh + - sudo bash /tmp/start-retailer.service.orders.sh + - inline: + - sudo bash /tmp/stop-retailer.service.orders.sh + - sudo bash /tmp/delete-retailer.service.orders.sh + when: destroy + retailer.service.orders~service.application#zip.archive::terraform@gcp.appengine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' + resource: + google_app_engine_standard_app_version: + app: + - delete_service_on_destroy: true + deployment: + - zip: + - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} + entrypoint: + - shell: '{{ SELF._management_start }}' + env_variables: {} + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + service_account: ${google_service_account.custom_service_account.email} + version_id: v1 + google_project_iam_member: + gae_api: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/compute.networkUser + storage_viewer: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/storage.objectViewer + google_service_account: + custom_service_account: + - account_id: '{{ SELF.application_name }}-account' + display_name: Custom Service Account + google_storage_bucket: + bucket: + - location: EU + name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' + google_storage_bucket_object: + object: + - bucket: ${google_storage_bucket.bucket.name} + name: object.zip + source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + retailer.service.orders~software.application#apt.archive::terraform@*->remote.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.orders {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-retailer.service.orders.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.orders.sh + - sudo bash /tmp/configure-retailer.service.orders.sh + - sudo bash /tmp/start-retailer.service.orders.sh + - inline: + - sudo bash /tmp/stop-retailer.service.orders.sh + - sudo bash /tmp/delete-retailer.service.orders.sh + when: destroy + retailer.service.orders~software.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.orders + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.orders {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.orders -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.orders.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.orders.sh + - sudo bash /tmp/configure-retailer.service.orders.sh + - sudo bash /tmp/start-retailer.service.orders.sh + - inline: + - sudo bash /tmp/stop-retailer.service.orders.sh + - sudo bash /tmp/delete-retailer.service.orders.sh + when: destroy + retailer.service.orders~software.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.orders + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.orders {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.orders -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.orders.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.orders.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.orders.sh + - sudo bash /tmp/configure-retailer.service.orders.sh + - sudo bash /tmp/start-retailer.service.orders.sh + - inline: + - sudo bash /tmp/stop-retailer.service.orders.sh + - sudo bash /tmp/delete-retailer.service.orders.sh + when: destroy + retailer.service.orders~service.application#docker.image::kubernetes@kubernetes.cluster: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: 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 }} 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 + retailer.service.orders~service.application#docker.image::compose@docker.engine->local.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 + retailer.service.orders~service.application#docker.image::compose@docker.engine->remote.machine: + derived_from: retailer.service.orders + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 }}' + retailer.service.global~service.application#docker.image::ansible@docker.engine->local.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + retailer.service.global~service.application#docker.image::ansible@docker.engine->remote.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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 }}' + retailer.service.global~service.application#docker.image::ansible@gcp.cloudrun: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: touch service + register: service + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.service.yaml' + - name: create service + ansible.builtin.copy: + dest: '{{ service.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + apiVersion: serving.knative.dev/v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + labels: + cloud.googleapis.com/location: '{{ SELF.gcp_region }}' + annotations: + run.googleapis.com/ingress: all + spec: + template: + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + containerPort: '{{ SELF.application_port }}' + env: [] + - name: apply service + ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet + args: + executable: /bin/bash + - name: touch policy + register: policy + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.policy.yaml' + - name: fill policy + ansible.builtin.copy: + dest: '{{ policy.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + bindings: + - members: + - allUsers + role: roles/run.invoker + - name: apply policy + ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + - name: describe service + register: service_description + ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + retailer.service.global~service.application#docker.image::ansible@kubernetes.cluster: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: create deployment + kubernetes.core.k8s: + wait: true + definition: + 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 }}' + - name: create service + kubernetes.core.k8s: + definition: + 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 + 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 }}' + retailer.service.global~service.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.global~service.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.global~service.application#zip.archive::ansible@gcp.appengine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: enable GCP AppEngine + ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + register: app_create_command + failed_when: + - "'Created' not in app_create_command.stderr" + - "'already contains' not in app_create_command.stderr" + - name: create working directory + register: directory + ansible.builtin.tempfile: + state: directory + - name: extract deployment artifact in working directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ directory.path }}' + - name: create specification + ansible.builtin.copy: + dest: '{{ directory.path }}/app.yaml' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + instance_class: F1 + env_variables: {} + - name: create app + ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet + args: + executable: /bin/bash + - name: browse app + register: browse_app + ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ browse_app.stdout[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet + args: + executable: /bin/bash + retailer.service.global~software.application#apt.package::ansible@*->remote.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.global~software.application#tar.archive::ansible@*->remote.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.global~software.application#zip.archive::ansible@*->remote.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + retailer.service.global~service.application#docker.image::terraform@docker.engine->local.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.global~service.application#docker.image::terraform@docker.engine->remote.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + retailer.service.global~service.application#docker.image::terraform@gcp.cloudrun: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' + resource: + google_cloud_run_v2_service: + application: + - ingress: INGRESS_TRAFFIC_ALL + location: '{{ SELF.gcp_region }}' + name: '{{ SELF.application_name }}' + template: + - containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + container_port: '{{ SELF.application_port }}' + env: [] + google_cloud_run_service_iam_binding: + application: + - location: '{{ SELF.gcp_region }}' + members: + - allUsers + role: roles/run.invoker + service: '{{ SELF.application_name }}' + retailer.service.global~service.application#docker.image::terraform@kubernetes.cluster: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_deployment_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - selector: + - match_labels: + app: '{{ SELF.application_name }}' + template: + - metadata: + - labels: + app: '{{ SELF.application_name }}' + spec: + - container: + - env: [] + image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + port: + - container_port: '{{ SELF.application_port }}' + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - port: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + target_port: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + retailer.service.global~service.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.global + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.global {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.global -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.global.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.global.sh + - sudo bash /tmp/configure-retailer.service.global.sh + - sudo bash /tmp/start-retailer.service.global.sh + - inline: + - sudo bash /tmp/stop-retailer.service.global.sh + - sudo bash /tmp/delete-retailer.service.global.sh + when: destroy + retailer.service.global~service.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.global + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.global {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.global -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-retailer.service.global.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.global.sh + - sudo bash /tmp/configure-retailer.service.global.sh + - sudo bash /tmp/start-retailer.service.global.sh + - inline: + - sudo bash /tmp/stop-retailer.service.global.sh + - sudo bash /tmp/delete-retailer.service.global.sh + when: destroy + retailer.service.global~service.application#zip.archive::terraform@gcp.appengine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' + resource: + google_app_engine_standard_app_version: + app: + - delete_service_on_destroy: true + deployment: + - zip: + - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} + entrypoint: + - shell: '{{ SELF._management_start }}' + env_variables: {} + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + service_account: ${google_service_account.custom_service_account.email} + version_id: v1 + google_project_iam_member: + gae_api: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/compute.networkUser + storage_viewer: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/storage.objectViewer + google_service_account: + custom_service_account: + - account_id: '{{ SELF.application_name }}-account' + display_name: Custom Service Account + google_storage_bucket: + bucket: + - location: EU + name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' + google_storage_bucket_object: + object: + - bucket: ${google_storage_bucket.bucket.name} + name: object.zip + source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + retailer.service.global~software.application#apt.archive::terraform@*->remote.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.global {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-retailer.service.global.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.global.sh + - sudo bash /tmp/configure-retailer.service.global.sh + - sudo bash /tmp/start-retailer.service.global.sh + - inline: + - sudo bash /tmp/stop-retailer.service.global.sh + - sudo bash /tmp/delete-retailer.service.global.sh + when: destroy + retailer.service.global~software.application#tar.archive::terraform@*->remote.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.global + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.global {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-retailer.service.global -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.global.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.global.sh + - sudo bash /tmp/configure-retailer.service.global.sh + - sudo bash /tmp/start-retailer.service.global.sh + - inline: + - sudo bash /tmp/stop-retailer.service.global.sh + - sudo bash /tmp/delete-retailer.service.global.sh + when: destroy + retailer.service.global~software.application#zip.archive::terraform@*->remote.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-retailer.service.global + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-retailer.service.global {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-retailer.service.global -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-retailer.service.global.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-retailer.service.global.sh + remote-exec: + - inline: + - sudo bash /tmp/create-retailer.service.global.sh + - sudo bash /tmp/configure-retailer.service.global.sh + - sudo bash /tmp/start-retailer.service.global.sh + - inline: + - sudo bash /tmp/stop-retailer.service.global.sh + - sudo bash /tmp/delete-retailer.service.global.sh + when: destroy + retailer.service.global~service.application#docker.image::kubernetes@kubernetes.cluster: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: 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 }} 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 + retailer.service.global~service.application#docker.image::compose@docker.engine->local.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 + retailer.service.global~service.application#docker.image::compose@docker.engine->remote.machine: + derived_from: retailer.service.global + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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---industry---plus-maintenance-automated/lib/rules.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml index 6f279bd251..2d6347a352 100644 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml @@ -5,6 +5,37 @@ ################################################### ansible: + - component: bucket + hosting: + - gcp.cloudstorage + weight: 0.5 + reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. + - component: bucket + hosting: + - minio.server + - '*' + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + - component: bucket + hosting: + - minio.server + - '*' + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + - component: bucket + hosting: + - minio.server + - kubernetes.cluster + weight: 1 + reason: Primary use case due to the specialization of Ansible. + - component: docker.engine + hosting: + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks' - component: docker.engine hosting: - remote.machine @@ -28,6 +59,13 @@ ansible: weight: 1 reason: Primary use case due to the specialization of Ansible. details: '"ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", "ansible.builtin.copy", and "ansible.builtin.systemd" tasks' + - component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. - component: mysql.database hosting: - mysql.dbms @@ -53,6 +91,14 @@ ansible: - remote.machine weight: 1 reason: Primary use case due to the specialization of Ansible. + - component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized + details: '"community.docker.docker_container" task' - component: mysql.dbms artifact: dbms.image hosting: @@ -82,6 +128,41 @@ ansible: weight: 1 reason: Primary use case due to the specialization of Ansible. details: '"ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks' + - component: bucket + artifact: cache.image + hosting: + - gcp.memorystore + weight: 0.5 + reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. + - component: redis.server + artifact: cache.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"community.docker.docker_container" task' + - component: redis.server + artifact: cache.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"community.docker.docker_container" task' + - component: redis.server + hosting: + - kubernetes.cluster + weight: 1 + reason: Primary use case due to the specialization of Ansible. + - component: service.application + artifact: docker.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"community.docker.docker_container" task' - component: service.application artifact: docker.image hosting: @@ -159,6 +240,37 @@ ansible: reason: Terraform is more specialized. details: '"openstack.cloud.security_group", "openstack.cloud.security_group_rule" and "openstack.cloud.server" tasks' terraform: + - component: bucket + hosting: + - gcp.cloudstorage + weight: 1 + reason: Terraform provides a declarative module. + - component: bucket + hosting: + - minio.server + - '*' + - local.machine + weight: 1 + reason: Terraform provides a declarative module. + - component: bucket + hosting: + - minio.server + - '*' + - remote.machine + weight: 1 + reason: Terraform provides a declarative module. + - component: bucket + hosting: + - minio.server + - kubernetes.cluster + weight: 1 + reason: Terraform provides a declarative module. + - component: docker.engine + hosting: + - local.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"local-exec" provider' - component: docker.engine hosting: - remote.machine @@ -182,6 +294,13 @@ terraform: weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' + - component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - local.machine + weight: 0.5 + reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. - component: mysql.database hosting: - mysql.dbms @@ -207,6 +326,14 @@ terraform: - remote.machine weight: 0.5 reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. + - component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' - component: mysql.dbms artifact: dbms.image hosting: @@ -236,6 +363,41 @@ terraform: weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' + - component: redis.server + artifact: cache.image + hosting: + - gcp.memorystore + weight: 1 + reason: Terraform provides a declarative module. + - component: redis.server + artifact: cache.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' + - component: redis.server + artifact: cache.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' + - component: redis.server + hosting: + - kubernetes.cluster + weight: 1 + reason: Terraform provides a declarative module. + - component: service.application + artifact: docker.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' - component: service.application artifact: docker.image hosting: @@ -340,6 +502,13 @@ kubernetes: reason: Kubernetes is the underlying technology. details: Kubernetes manifest generated and applied compose: + - component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - local.machine + weight: 0 + reason: One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. - component: mysql.database hosting: - mysql.dbms @@ -347,6 +516,14 @@ compose: - remote.machine weight: 0 reason: One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. + - component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - local.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker-compose manifest generated and applied - component: mysql.dbms artifact: dbms.image hosting: @@ -355,6 +532,30 @@ compose: weight: 1 reason: Docker is the underlying technology. details: docker-compose manifest generated and applied + - component: redis.server + artifact: cache.image + hosting: + - docker.engine + - local.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker compose manifest generated and applied + - component: redis.server + artifact: cache.image + hosting: + - docker.engine + - remote.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker compose manifest generated and applied + - component: service.application + artifact: docker.image + hosting: + - docker.engine + - local.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker compose manifest generated and applied - component: service.application artifact: docker.image hosting: diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml index 5fdd64d120..717e952e1c 100644 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml @@ -72,6 +72,9 @@ artifact_types: dbms.image: derived_from: artifact description: expects image reference in "file" + cache.image: + derived_from: artifact + description: expects image reference in "file" interface_types: interface: derived_from: tosca.interfaces.Root @@ -230,10 +233,16 @@ node_types: properties: machine_name: type: string + attributes: + application_address: + type: string + management_address: + type: string local.machine: derived_from: machine metadata: vintner_normative: 'true' + vintner_abstract: 'true' capabilities: host: type: tosca.capabilities.Compute @@ -259,13 +268,6 @@ node_types: type: string ssh_key_file: type: string - attributes: - management_address: - type: string - application_address: - type: string - default: - eval: .::management_address capabilities: host: type: tosca.capabilities.Compute @@ -275,6 +277,10 @@ node_types: connection: ssh host: eval: .parent::management_address + attributes: + application_address: + default: + eval: .::management_address virtual.machine: derived_from: remote.machine physical.machine: @@ -303,6 +309,8 @@ node_types: metadata: vintner_normative: 'true' vintner_abstract: 'true' + cache: + derived_from: software.application storage: derived_from: node block.storage: @@ -356,3 +364,2139 @@ node_types: - host: capability: tosca.capabilities.Compute relationship: tosca.relationships.HostedOn + + # [OPENTOSCA_VINTNER_GENERATION_MARK] + + ################################################################ + # + # WARNING: Do not edit! This following content is autogenerated! + # + ################################################################ + + virtual.machine~virtual.machine#machine.image::ansible@openstack.provider: + derived_from: virtual.machine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_region_name: + type: string + default: + get_input: os_region_name + os_auth_type: + type: string + default: + get_input: os_auth_type + os_auth_url: + type: string + default: + get_input: os_auth_url + os_identity_api_version: + type: string + default: + get_input: os_identity_api_version + os_interface: + type: string + default: + get_input: os_interface + os_application_credential_id: + type: string + default: + get_input: os_application_credential_id + os_application_credential_secret: + type: string + default: + get_input: os_application_credential_secret + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + OS_AUTH_TYPE: + eval: .::os_auth_type + OS_AUTH_URL: + eval: .::os_auth_url + OS_IDENTITY_API_VERSION: + eval: .::os_identity_api_version + OS_REGION_NAME: + eval: .::os_region_name + OS_INTERFACE: + eval: .::os_interface + OS_APPLICATION_CREDENTIAL_ID: + eval: .::os_application_credential_id + OS_APPLICATION_CREDENTIAL_SECRET: + eval: .::os_application_credential_secret + inputs: + playbook: + q: + - name: Create security group + openstack.cloud.security_group: + name: '{{ SELF.machine_name }}' + - name: Open ports + openstack.cloud.security_group_rule: + security_group: '{{ SELF.machine_name }}' + protocol: tcp + port_range_min: '{{ item }}' + port_range_max: '{{ item }}' + remote_ip_prefix: 0.0.0.0/0 + direction: ingress + ethertype: IPv4 + loop: '{{ SELF.ports | join("::") | split("::") | map("int") }}' + - name: Create VM + openstack.cloud.server: + state: present + name: '{{ SELF.machine_name }}' + image: '{{ ".artifacts::machine_image::file" | eval }}' + key_name: default + flavor: '{{ SELF.flavor }}' + network: '{{ SELF.network }}' + security_groups: "{{ 'default,' + SELF.machine_name }}" + auto_ip: false + timeout: 360 + register: server_info + - name: Set attributes + set_fact: + management_address: '{{ server_info.server.accessIPv4 }}' + resultTemplate: | + name: SELF + attributes: + management_address: '{{ outputs.management_address | trim }}' + outputs: + management_address: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: Delete VM + openstack.cloud.server: + state: absent + name: '{{ SELF.machine_name }}' + delete_fip: true + timeout: 360 + - name: Delete security group + openstack.cloud.security_group: + state: absent + name: '{{ SELF.machine_name }}' + virtual.machine~virtual.machine#machine.image::terraform@openstack.provider: + derived_from: virtual.machine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_region_name: + type: string + default: + get_input: os_region_name + os_auth_type: + type: string + default: + get_input: os_auth_type + os_auth_url: + type: string + default: + get_input: os_auth_url + os_identity_api_version: + type: string + default: + get_input: os_identity_api_version + os_interface: + type: string + default: + get_input: os_interface + os_application_credential_id: + type: string + default: + get_input: os_application_credential_id + os_application_credential_secret: + type: string + default: + get_input: os_application_credential_secret + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + management_address: management_address + inputs: + main: + terraform: + - required_providers: + - openstack: + source: terraform-provider-openstack/openstack + version: ~> 1.48.0 + required_version: '>= 0.14.0' + provider: + openstack: + - application_credential_id: '{{ SELF.os_application_credential_id }}' + application_credential_secret: '{{ SELF.os_application_credential_secret }}' + auth_url: '{{ SELF.os_auth_url }}' + region: '{{ SELF.os_region_name }}' + output: + management_address: + - value: ${yamldecode(openstack_compute_instance_v2.machine.access_ip_v4)} + resource: + openstack_compute_instance_v2: + machine: + - flavor_name: '{{ SELF.flavor }}' + image_name: '{{ ".artifacts::machine_image::file" | eval }}' + key_pair: default + name: '{{ SELF.machine_name }}' + network: + - name: '{{ SELF.network }}' + security_groups: + - default + - ${openstack_networking_secgroup_v2.ports.name} + openstack_networking_secgroup_rule_v2: + port: + - direction: ingress + ethertype: IPv4 + for_each: ${toset(split("::", "{{ SELF.ports | join("::") }}"))} + port_range_max: ${each.value} + port_range_min: ${each.value} + protocol: tcp + remote_ip_prefix: 0.0.0.0/0 + security_group_id: ${openstack_networking_secgroup_v2.ports.id} + openstack_networking_secgroup_v2: + ports: + - name: '{{ SELF.machine_name }}' + cache~software.application#apt.package::ansible@*->remote.machine: + derived_from: cache + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + cache~software.application#tar.archive::ansible@*->remote.machine: + derived_from: cache + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + cache~software.application#zip.archive::ansible@*->remote.machine: + derived_from: cache + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + cache~software.application#apt.archive::terraform@*->remote.machine: + derived_from: cache + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-cache {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-cache.sh + remote-exec: + - inline: + - sudo bash /tmp/create-cache.sh + - sudo bash /tmp/configure-cache.sh + - sudo bash /tmp/start-cache.sh + - inline: + - sudo bash /tmp/stop-cache.sh + - sudo bash /tmp/delete-cache.sh + when: destroy + cache~software.application#tar.archive::terraform@*->remote.machine: + derived_from: cache + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-cache + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-cache {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-cache -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-cache.sh + remote-exec: + - inline: + - sudo bash /tmp/create-cache.sh + - sudo bash /tmp/configure-cache.sh + - sudo bash /tmp/start-cache.sh + - inline: + - sudo bash /tmp/stop-cache.sh + - sudo bash /tmp/delete-cache.sh + when: destroy + cache~software.application#zip.archive::terraform@*->remote.machine: + derived_from: cache + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-cache + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-cache {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-cache -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-cache.sh + remote-exec: + - inline: + - sudo bash /tmp/create-cache.sh + - sudo bash /tmp/configure-cache.sh + - sudo bash /tmp/start-cache.sh + - inline: + - sudo bash /tmp/stop-cache.sh + - sudo bash /tmp/delete-cache.sh + when: destroy + bucket~bucket::ansible@gcp.cloudstorage: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: [] + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: [] + bucket~bucket::ansible@minio.server->*->local.machine: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + bucket~bucket::ansible@minio.server->*->remote.machine: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + bucket~bucket::ansible@minio.server->kubernetes.cluster: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + bucket~bucket#cache.image::ansible@gcp.memorystore: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: [] + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: [] + bucket~bucket::terraform@gcp.cloudstorage: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + delete: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + mysql: + source: petoju/mysql + version: 3.0.48 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + resource: {} + bucket~bucket::terraform@minio.server->*->local.machine: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: [] + provider: {} + resource: {} + bucket~bucket::terraform@minio.server->*->remote.machine: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + delete: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + defaults: + inputs: + main: + terraform: [] + provider: {} + resource: {} + bucket~bucket::terraform@minio.server->kubernetes.cluster: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + delete: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + defaults: + inputs: + main: + terraform: [] + provider: {} + resource: {} + ingress~ingress::ansible@kubernetes.cluster: + derived_from: ingress + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: not implemented + interfaces: + Standard: + operations: + create: + 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: apply service + kubernetes.core.k8s: + definition: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}-external' + namespace: default + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: 80 + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: LoadBalancer + ingress~ingress::ansible@remote.machine: + derived_from: ingress + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::application_address + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: add apt key + ansible.builtin.apt_key: + url: https://dl.cloudsmith.io/public/caddy/stable/gpg.key + keyring: /usr/share/keyrings/caddy-stable-archive-keyring.gpg + state: present + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/caddy-stable-archive-keyring.gpg] https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main + filename: caddy-stable + state: present + - name: install package + ansible.builtin.apt: + name: caddy + state: present + update_cache: 'yes' + - name: configure caddy + ansible.builtin.copy: + dest: /etc/caddy/Caddyfile + content: | + :80 { + reverse_proxy localhost:{{ SELF.application_port }} + } + - name: restart caddy + ansible.builtin.systemd: + name: caddy + state: reloaded + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: not implemented + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}-external' + wait_for_load_balancer: false + spec: + - port: + - name: '{{ SELF.application_protocol }}' + port: 80 + target_port: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: LoadBalancer + ingress~ingress::terraform@remote.machine: + derived_from: ingress + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::application_address + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + + #!/usr/bin/bash + set -e + + # Install caddy + apt-get install -y debian-keyring debian-archive-keyring apt-transport-https curl + curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/gpg.key | gpg --dearmor --yes -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg + curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt | tee /etc/apt/sources.list.d/caddy-stable.list + apt-get update + apt-get install caddy -y + + # Configure caddy + cat < /etc/caddy/Caddyfile + :80 { + reverse_proxy localhost:{{ SELF.application_port }} + } + EOF + + # Restart caddy + systemctl reload caddy + destination: /tmp/install-ingress.sh + remote-exec: + - inline: + - sudo bash /tmp/install-ingress.sh + ingress~ingress::kubernetes@kubernetes.cluster: + derived_from: ingress + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: not implemented + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: touch manifest + register: manifest + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.ingress.manifest.yaml' + - name: create manifest + ansible.builtin.copy: + dest: '{{ manifest.path }}' + content: '{{ service | to_yaml }}' + vars: + service: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}-external' + spec: + ports: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + targetPort: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: LoadBalancer + - 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 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml index 06693333a1..cba7faf8a5 100644 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml @@ -99,6 +99,15 @@ node_types: operations: configure: npm ci start: npm start + reactjs.service.application: + derived_from: service.application + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + application_language: + type: string + default: nodejs18 python.runtime: derived_from: software.runtime metadata: @@ -328,6 +337,14 @@ node_types: gcp_service: type: string default: storage.googleapis.com + gcp.memorystore: + derived_from: gcp.service + metadata: + vintner_normative: 'true' + properties: + gcp_service: + type: string + default: redis.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 @@ -467,4 +484,15709 @@ node_types: capability: tosca.capabilities.Compute relationship: tosca.relationships.HostedOn minio.server: - derived_from: software.application + derived_from: service.application + metadata: + vintner_normative: 'true' + redis.server: + derived_from: cache + metadata: + vintner_normative: 'true' + properties: + cache_name: + type: string + cache_port: + type: string + application_protocol: + type: string + default: redis + application_name: + default: + eval: .::cache_name + application_port: + default: + eval: .::cache_port + + # [OPENTOSCA_VINTNER_GENERATION_MARK] + + ################################################################ + # + # WARNING: Do not edit! This following content is autogenerated! + # + ################################################################ + + nodejs.runtime~software.application#apt.package::ansible@*->remote.machine: + derived_from: nodejs.runtime + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + nodejs.runtime~software.application#tar.archive::ansible@*->remote.machine: + derived_from: nodejs.runtime + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: APPLICATION_NAME="{{ SELF.application_name }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + nodejs.runtime~software.application#zip.archive::ansible@*->remote.machine: + derived_from: nodejs.runtime + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: APPLICATION_NAME="{{ SELF.application_name }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + nodejs.runtime~software.application#apt.archive::terraform@*->remote.machine: + derived_from: nodejs.runtime + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-nodejs.runtime {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-nodejs.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-nodejs.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-nodejs.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-nodejs.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-nodejs.runtime.sh + remote-exec: + - inline: + - sudo bash /tmp/create-nodejs.runtime.sh + - sudo bash /tmp/configure-nodejs.runtime.sh + - sudo bash /tmp/start-nodejs.runtime.sh + - inline: + - sudo bash /tmp/stop-nodejs.runtime.sh + - sudo bash /tmp/delete-nodejs.runtime.sh + when: destroy + nodejs.runtime~software.application#tar.archive::terraform@*->remote.machine: + derived_from: nodejs.runtime + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-nodejs.runtime + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-nodejs.runtime {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-nodejs.runtime -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-nodejs.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-nodejs.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-nodejs.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-nodejs.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-nodejs.runtime.sh + remote-exec: + - inline: + - sudo bash /tmp/create-nodejs.runtime.sh + - sudo bash /tmp/configure-nodejs.runtime.sh + - sudo bash /tmp/start-nodejs.runtime.sh + - inline: + - sudo bash /tmp/stop-nodejs.runtime.sh + - sudo bash /tmp/delete-nodejs.runtime.sh + when: destroy + nodejs.runtime~software.application#zip.archive::terraform@*->remote.machine: + derived_from: nodejs.runtime + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-nodejs.runtime + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-nodejs.runtime {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-nodejs.runtime -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-nodejs.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-nodejs.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-nodejs.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-nodejs.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-nodejs.runtime.sh + remote-exec: + - inline: + - sudo bash /tmp/create-nodejs.runtime.sh + - sudo bash /tmp/configure-nodejs.runtime.sh + - sudo bash /tmp/start-nodejs.runtime.sh + - inline: + - sudo bash /tmp/stop-nodejs.runtime.sh + - sudo bash /tmp/delete-nodejs.runtime.sh + when: destroy + python.runtime~software.application#apt.package::ansible@*->remote.machine: + derived_from: python.runtime + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + python.runtime~software.application#tar.archive::ansible@*->remote.machine: + derived_from: python.runtime + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + python.runtime~software.application#zip.archive::ansible@*->remote.machine: + derived_from: python.runtime + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + python.runtime~software.application#apt.archive::terraform@*->remote.machine: + derived_from: python.runtime + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-python.runtime {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-python.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-python.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-python.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-python.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-python.runtime.sh + remote-exec: + - inline: + - sudo bash /tmp/create-python.runtime.sh + - sudo bash /tmp/configure-python.runtime.sh + - sudo bash /tmp/start-python.runtime.sh + - inline: + - sudo bash /tmp/stop-python.runtime.sh + - sudo bash /tmp/delete-python.runtime.sh + when: destroy + python.runtime~software.application#tar.archive::terraform@*->remote.machine: + derived_from: python.runtime + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-python.runtime + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-python.runtime {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-python.runtime -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-python.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-python.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-python.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-python.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-python.runtime.sh + remote-exec: + - inline: + - sudo bash /tmp/create-python.runtime.sh + - sudo bash /tmp/configure-python.runtime.sh + - sudo bash /tmp/start-python.runtime.sh + - inline: + - sudo bash /tmp/stop-python.runtime.sh + - sudo bash /tmp/delete-python.runtime.sh + when: destroy + python.runtime~software.application#zip.archive::terraform@*->remote.machine: + derived_from: python.runtime + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-python.runtime + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-python.runtime {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-python.runtime -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-python.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-python.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-python.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-python.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-python.runtime.sh + remote-exec: + - inline: + - sudo bash /tmp/create-python.runtime.sh + - sudo bash /tmp/configure-python.runtime.sh + - sudo bash /tmp/start-python.runtime.sh + - inline: + - sudo bash /tmp/stop-python.runtime.sh + - sudo bash /tmp/delete-python.runtime.sh + when: destroy + java.runtime~software.application#apt.package::ansible@*->remote.machine: + derived_from: java.runtime + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + java.runtime~software.application#tar.archive::ansible@*->remote.machine: + derived_from: java.runtime + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: APPLICATION_NAME="{{ SELF.application_name }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + java.runtime~software.application#zip.archive::ansible@*->remote.machine: + derived_from: java.runtime + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: APPLICATION_NAME="{{ SELF.application_name }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + java.runtime~software.application#apt.archive::terraform@*->remote.machine: + derived_from: java.runtime + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-java.runtime {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-java.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-java.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-java.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-java.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-java.runtime.sh + remote-exec: + - inline: + - sudo bash /tmp/create-java.runtime.sh + - sudo bash /tmp/configure-java.runtime.sh + - sudo bash /tmp/start-java.runtime.sh + - inline: + - sudo bash /tmp/stop-java.runtime.sh + - sudo bash /tmp/delete-java.runtime.sh + when: destroy + java.runtime~software.application#tar.archive::terraform@*->remote.machine: + derived_from: java.runtime + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-java.runtime + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-java.runtime {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-java.runtime -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-java.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-java.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-java.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-java.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-java.runtime.sh + remote-exec: + - inline: + - sudo bash /tmp/create-java.runtime.sh + - sudo bash /tmp/configure-java.runtime.sh + - sudo bash /tmp/start-java.runtime.sh + - inline: + - sudo bash /tmp/stop-java.runtime.sh + - sudo bash /tmp/delete-java.runtime.sh + when: destroy + java.runtime~software.application#zip.archive::terraform@*->remote.machine: + derived_from: java.runtime + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-java.runtime + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-java.runtime {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-java.runtime -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-java.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-java.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-java.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-java.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-java.runtime.sh + remote-exec: + - inline: + - sudo bash /tmp/create-java.runtime.sh + - sudo bash /tmp/configure-java.runtime.sh + - sudo bash /tmp/start-java.runtime.sh + - inline: + - sudo bash /tmp/stop-java.runtime.sh + - sudo bash /tmp/delete-java.runtime.sh + when: destroy + dotnet.runtime~software.application#apt.package::ansible@*->remote.machine: + derived_from: dotnet.runtime + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + dotnet.runtime~software.application#tar.archive::ansible@*->remote.machine: + derived_from: dotnet.runtime + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: APPLICATION_NAME="{{ SELF.application_name }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + dotnet.runtime~software.application#zip.archive::ansible@*->remote.machine: + derived_from: dotnet.runtime + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: APPLICATION_NAME="{{ SELF.application_name }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + dotnet.runtime~software.application#apt.archive::terraform@*->remote.machine: + derived_from: dotnet.runtime + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-dotnet.runtime {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-dotnet.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-dotnet.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-dotnet.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-dotnet.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-dotnet.runtime.sh + remote-exec: + - inline: + - sudo bash /tmp/create-dotnet.runtime.sh + - sudo bash /tmp/configure-dotnet.runtime.sh + - sudo bash /tmp/start-dotnet.runtime.sh + - inline: + - sudo bash /tmp/stop-dotnet.runtime.sh + - sudo bash /tmp/delete-dotnet.runtime.sh + when: destroy + dotnet.runtime~software.application#tar.archive::terraform@*->remote.machine: + derived_from: dotnet.runtime + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-dotnet.runtime + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-dotnet.runtime {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-dotnet.runtime -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-dotnet.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-dotnet.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-dotnet.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-dotnet.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-dotnet.runtime.sh + remote-exec: + - inline: + - sudo bash /tmp/create-dotnet.runtime.sh + - sudo bash /tmp/configure-dotnet.runtime.sh + - sudo bash /tmp/start-dotnet.runtime.sh + - inline: + - sudo bash /tmp/stop-dotnet.runtime.sh + - sudo bash /tmp/delete-dotnet.runtime.sh + when: destroy + dotnet.runtime~software.application#zip.archive::terraform@*->remote.machine: + derived_from: dotnet.runtime + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-dotnet.runtime + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-dotnet.runtime {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-dotnet.runtime -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-dotnet.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-dotnet.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-dotnet.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-dotnet.runtime.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-dotnet.runtime.sh + remote-exec: + - inline: + - sudo bash /tmp/create-dotnet.runtime.sh + - sudo bash /tmp/configure-dotnet.runtime.sh + - sudo bash /tmp/start-dotnet.runtime.sh + - inline: + - sudo bash /tmp/stop-dotnet.runtime.sh + - sudo bash /tmp/delete-dotnet.runtime.sh + when: destroy + gcp.cloudrun~gcp.service::ansible: + derived_from: gcp.cloudrun + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: + - name: enable service + google.cloud.gcp_serviceusage_service: + name: '{{ SELF.gcp_service }}' + project: '{{ SELF.gcp_project }}' + delete: exit 0 + gcp.cloudrun~gcp.service::terraform: + derived_from: gcp.cloudrun + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 4.67.0 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + resource: + google_project_service: + cloud_sql_admin: + - disable_on_destroy: false + project: '{{ SELF.gcp_project }}' + service: '{{ SELF.gcp_service }}' + gcp.cloudsql~gcp.service::ansible: + derived_from: gcp.cloudsql + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: + - name: enable service + google.cloud.gcp_serviceusage_service: + name: '{{ SELF.gcp_service }}' + project: '{{ SELF.gcp_project }}' + delete: exit 0 + gcp.cloudsql~gcp.service::terraform: + derived_from: gcp.cloudsql + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 4.67.0 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + resource: + google_project_service: + cloud_sql_admin: + - disable_on_destroy: false + project: '{{ SELF.gcp_project }}' + service: '{{ SELF.gcp_service }}' + gcp.appengine~gcp.service::ansible: + derived_from: gcp.appengine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: + - name: enable service + google.cloud.gcp_serviceusage_service: + name: '{{ SELF.gcp_service }}' + project: '{{ SELF.gcp_project }}' + delete: exit 0 + gcp.appengine~gcp.service::terraform: + derived_from: gcp.appengine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 4.67.0 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + resource: + google_project_service: + cloud_sql_admin: + - disable_on_destroy: false + project: '{{ SELF.gcp_project }}' + service: '{{ SELF.gcp_service }}' + gcp.appenginereporting~gcp.service::ansible: + derived_from: gcp.appenginereporting + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: + - name: enable service + google.cloud.gcp_serviceusage_service: + name: '{{ SELF.gcp_service }}' + project: '{{ SELF.gcp_project }}' + delete: exit 0 + gcp.appenginereporting~gcp.service::terraform: + derived_from: gcp.appenginereporting + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 4.67.0 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + resource: + google_project_service: + cloud_sql_admin: + - disable_on_destroy: false + project: '{{ SELF.gcp_project }}' + service: '{{ SELF.gcp_service }}' + gcp.cloudbuild~gcp.service::ansible: + derived_from: gcp.cloudbuild + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: + - name: enable service + google.cloud.gcp_serviceusage_service: + name: '{{ SELF.gcp_service }}' + project: '{{ SELF.gcp_project }}' + delete: exit 0 + gcp.cloudbuild~gcp.service::terraform: + derived_from: gcp.cloudbuild + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 4.67.0 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + resource: + google_project_service: + cloud_sql_admin: + - disable_on_destroy: false + project: '{{ SELF.gcp_project }}' + service: '{{ SELF.gcp_service }}' + gcp.kubernetesengine~gcp.service::ansible: + derived_from: gcp.kubernetesengine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: + - name: enable service + google.cloud.gcp_serviceusage_service: + name: '{{ SELF.gcp_service }}' + project: '{{ SELF.gcp_project }}' + delete: exit 0 + gcp.kubernetesengine~gcp.service::terraform: + derived_from: gcp.kubernetesengine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 4.67.0 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + resource: + google_project_service: + cloud_sql_admin: + - disable_on_destroy: false + project: '{{ SELF.gcp_project }}' + service: '{{ SELF.gcp_service }}' + gcp.cloudstorage~gcp.service::ansible: + derived_from: gcp.cloudstorage + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: + - name: enable service + google.cloud.gcp_serviceusage_service: + name: '{{ SELF.gcp_service }}' + project: '{{ SELF.gcp_project }}' + delete: exit 0 + gcp.cloudstorage~gcp.service::terraform: + derived_from: gcp.cloudstorage + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 4.67.0 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + resource: + google_project_service: + cloud_sql_admin: + - disable_on_destroy: false + project: '{{ SELF.gcp_project }}' + service: '{{ SELF.gcp_service }}' + gcp.memorystore~gcp.service::ansible: + derived_from: gcp.memorystore + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: + - name: enable service + google.cloud.gcp_serviceusage_service: + name: '{{ SELF.gcp_service }}' + project: '{{ SELF.gcp_project }}' + delete: exit 0 + gcp.memorystore~gcp.service::terraform: + derived_from: gcp.memorystore + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 4.67.0 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + resource: + google_project_service: + cloud_sql_admin: + - disable_on_destroy: false + project: '{{ SELF.gcp_project }}' + service: '{{ SELF.gcp_service }}' + docker.engine~docker.engine::ansible@local.machine: + derived_from: docker.engine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install docker + 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 + - name: add user to docker group + ansible.builtin.user: + name: '{{ SELF.os_ssh_user }}' + groups: docker + append: 'yes' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - 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 + docker.engine~docker.engine::ansible@remote.machine: + derived_from: docker.engine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install docker + 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 + - name: add user to docker group + ansible.builtin.user: + name: '{{ SELF.os_ssh_user }}' + groups: docker + append: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + docker.engine~software.application#tar.archive::ansible@*->remote.machine: + derived_from: docker.engine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: |- + APPLICATION_NAME="{{ SELF.application_name }}" + _HOSTING="{{ SELF._hosting }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + docker.engine~software.application#zip.archive::ansible@*->remote.machine: + derived_from: docker.engine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: |- + APPLICATION_NAME="{{ SELF.application_name }}" + _HOSTING="{{ SELF._hosting }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + docker.engine~docker.engine::terraform@local.machine: + derived_from: docker.engine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - mysql: + source: hashicorp/local + version: 2.5.1 + provider: + local: + - endpoint: 127.0.0.1:{{ HOST.management_port }} + password: '{{ HOST.dbms_password }}' + username: root + resource: + local_file: + tmp_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 + # 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 + filename: /tmp/docker.service + terraform_data: + docker: + - depends_on: local_file.tmp_service + provisioner: + local-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~docker.engine::terraform@remote.machine: + derived_from: docker.engine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + docker: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + 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: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + _HOSTING="{{ SELF._hosting }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-docker.engine {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-docker.engine.sh + remote-exec: + - inline: + - sudo bash /tmp/create-docker.engine.sh + - sudo bash /tmp/configure-docker.engine.sh + - sudo bash /tmp/start-docker.engine.sh + - inline: + - sudo bash /tmp/stop-docker.engine.sh + - sudo bash /tmp/delete-docker.engine.sh + when: destroy + docker.engine~software.application#tar.archive::terraform@*->remote.machine: + derived_from: docker.engine + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-docker.engine + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + _HOSTING="{{ SELF._hosting }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-docker.engine {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-docker.engine -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-docker.engine.sh + remote-exec: + - inline: + - sudo bash /tmp/create-docker.engine.sh + - sudo bash /tmp/configure-docker.engine.sh + - sudo bash /tmp/start-docker.engine.sh + - inline: + - sudo bash /tmp/stop-docker.engine.sh + - sudo bash /tmp/delete-docker.engine.sh + when: destroy + docker.engine~software.application#zip.archive::terraform@*->remote.machine: + derived_from: docker.engine + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-docker.engine + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + _HOSTING="{{ SELF._hosting }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-docker.engine {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-docker.engine -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-docker.engine.sh + remote-exec: + - inline: + - sudo bash /tmp/create-docker.engine.sh + - sudo bash /tmp/configure-docker.engine.sh + - sudo bash /tmp/start-docker.engine.sh + - inline: + - sudo bash /tmp/stop-docker.engine.sh + - sudo bash /tmp/delete-docker.engine.sh + when: destroy + mysql.dbms~mysql.dbms#dbms.image::ansible@docker.engine->local.machine: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + application_port: + type: string + default: 3306 + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: 3306 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.dbms_name }}' + image: mysql:{{ ".artifacts::dbms_image::file" | eval }} + network_mode: host + env: + MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password | string }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: delete container + community.docker.docker_container: + name: '{{ SELF.dbms_name }}' + state: absent + mysql.dbms~mysql.dbms#dbms.image::ansible@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: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + application_port: + type: string + default: 3306 + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: 3306 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.dbms_name }}' + image: mysql:{{ ".artifacts::dbms_image::file" | eval }} + network_mode: host + env: + MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password | string }}' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + dbms_ssl_mode: + type: string + default: Preferred + attributes: + application_port: + type: string + default: 3306 + management_address: + type: string + default: + eval: .::application_address + management_port: + type: integer + default: + eval: .::application_port + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: + - name: create a instance + register: instance_info + google.cloud.gcp_sql_instance: + name: '{{ SELF.dbms_name }}' + database_version: MYSQL_{{ ".artifacts::dbms_image::file" | eval | replace(".", "_") }} + settings: + tier: db-f1-micro + availability_type: REGIONAL + backup_configuration: + binary_log_enabled: true + enabled: true + ip_configuration: + authorized_networks: + - value: 0.0.0.0/0 + region: '{{ SELF.gcp_region }}' + project: '{{ SELF.gcp_project }}' + - name: set root password + google.cloud.gcp_sql_user: + name: root + host: '%' + password: '{{ SELF.dbms_password }}' + instance: '{{ instance_info }}' + project: '{{ SELF.gcp_project }}' + - name: aet attributes + set_fact: + application_address: '{{ instance_info.ipAddresses[0].ipAddress | trim }}' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address }}' + outputs: + application_address: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: Activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: Delete Instance + ansible.builtin.shell: gcloud sql instances delete {{ SELF.dbms_name }} --quiet + args: + executable: /bin/bash + mysql.dbms~mysql.dbms#dbms.image::ansible@kubernetes.cluster: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::dbms_name + application_port: + type: integer + default: 3306 + management_address: + type: string + default: + eval: .::application_address + management_port: + type: integer + default: + eval: .::application_port + interfaces: + Standard: + operations: + create: + 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: create deployment + kubernetes.core.k8s: + wait: true + definition: + 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 + - name: create service + kubernetes.core.k8s: + definition: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.dbms_name }}' + namespace: default + spec: + ports: + - name: mysql + port: 3306 + targetPort: 3306 + selector: + app: '{{ SELF.dbms_name }}' + type: ClusterIP + 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: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_port: + type: string + default: 3001 + application_address: + type: string + default: 127.0.0.1 + attributes: + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: + eval: .::application_port + capabilities: + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: installing mysql + ansible.builtin.apt: + name: + - mysql-server + - mysql-client + - python3-mysqldb + - libmysqlclient-dev + state: present + update_cache: 'yes' + - name: start and enable mysql service + ansible.builtin.systemd: + name: mysql + state: started + enabled: 'yes' + - name: enable passwordless login + ansible.builtin.copy: + dest: '{{ item }}' + content: | + [client] + user=root + password={{ SELF.dbms_password }} + loop: + - /root/.my.cnf + - /home/{{ SELF.os_ssh_user }}/.my.cnf + - 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 + 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 + ansible.builtin.systemd: + name: mysql + state: restarted + - name: create all root + community.mysql.mysql_user: + name: root + password: '{{ SELF.dbms_password }}' + priv: '*.*:ALL' + host: '%' + state: present + login_host: localhost + login_password: '{{ SELF.dbms_password }}' + login_port: '{{ SELF.application_port }}' + login_user: root + - name: delete localhost root + community.mysql.mysql_user: + name: root + host: localhost + state: absent + login_host: localhost + login_password: '{{ SELF.dbms_password }}' + login_port: '{{ SELF.application_port }}' + login_user: root + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + mysql.dbms~software.application#tar.archive::ansible@*->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: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: |- + DBMS_NAME="{{ SELF.dbms_name }}" + APPLICATION_NAME="{{ SELF.application_name }}" + DBMS_PASSWORD="{{ SELF.dbms_password }}" + DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + mysql.dbms~software.application#zip.archive::ansible@*->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: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: |- + DBMS_NAME="{{ SELF.dbms_name }}" + APPLICATION_NAME="{{ SELF.application_name }}" + DBMS_PASSWORD="{{ SELF.dbms_password }}" + DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + mysql.dbms~mysql.dbms#dbms.image::terraform@docker.engine->local.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: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + application_port: + type: integer + default: 3306 + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: 3306 + capabilities: + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - name: '{{ SELF.dbms_name }}' + image: ${docker_image.image.image_id} + network_mode: host + env: + - MYSQL_ROOT_PASSWORD={{ SELF.dbms_password }} + docker_image: + image: + - name: mysql:{{ ".artifacts::dbms_image::file" | eval }} + mysql.dbms~mysql.dbms#dbms.image::terraform@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: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + application_port: + type: integer + default: 3306 + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: 3306 + capabilities: + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - name: '{{ SELF.dbms_name }}' + image: ${docker_image.image.image_id} + network_mode: host + env: + - MYSQL_ROOT_PASSWORD={{ SELF.dbms_password }} + docker_image: + image: + - name: mysql:{{ ".artifacts::dbms_image::file" | eval }} + mysql.dbms~mysql.dbms#dbms.image::terraform@gcp.cloudsql: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + dbms_ssl_mode: + type: string + default: Preferred + attributes: + application_port: + type: string + default: 3306 + management_address: + type: string + default: + eval: .::application_address + management_port: + type: integer + default: + eval: .::application_port + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 4.67.0 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: ${google_sql_database_instance.dbms.public_ip_address} + resource: + google_sql_database_instance: + dbms: + - database_version: MYSQL_{{ ".artifacts::dbms_image::file" | eval | replace(".", "_") }} + deletion_protection: false + name: '{{ SELF.dbms_name }}' + root_password: '{{ SELF.dbms_password }}' + settings: + - availability_type: REGIONAL + backup_configuration: + - binary_log_enabled: true + enabled: true + ip_configuration: + - authorized_networks: + - name: public + value: 0.0.0.0/0 + ipv4_enabled: true + tier: db-f1-micro + google_sql_user: + user: + - host: '%' + instance: ${google_sql_database_instance.dbms.name} + name: root + password: ${google_sql_database_instance.dbms.root_password} + mysql.dbms~mysql.dbms#dbms.image::terraform@kubernetes.cluster: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::dbms_name + application_port: + type: integer + default: 3306 + management_address: + type: string + default: + eval: .::application_address + management_port: + type: integer + default: + eval: .::application_port + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_deployment_v1: + application: + - metadata: + - name: '{{ SELF.dbms_name }}' + spec: + - selector: + - match_labels: + app: '{{ SELF.dbms_name }}' + template: + - metadata: + - labels: + app: '{{ SELF.dbms_name }}' + spec: + - container: + - name: '{{ SELF.dbms_name }}' + image: mysql:{{ ".artifacts::dbms_image::file" | eval }} + env: + - name: MYSQL_ROOT_PASSWORD + value: '{{ SELF.dbms_password }}' + port: + - container_port: 3306 + name: mysql + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.dbms_name }}' + spec: + - port: + - name: mysql + port: 3306 + target_port: 3306 + selector: + app: '{{ SELF.dbms_name }}' + type: ClusterIP + mysql.dbms~mysql.dbms#dbms.image::terraform@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: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_port: + type: string + default: 3001 + application_address: + type: string + default: 127.0.0.1 + attributes: + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: + eval: .::application_port + capabilities: + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + + #!/usr/bin/bash + set -e + export DEBIAN_FRONTEND="noninteractive" + + DBMS_PASSWORD=$1 + DBMS_PORT=$2 + + # Set password + debconf-set-selections <<< "mysql-server mysql-server/root_password password ${DBMS_PASSWORD}" + debconf-set-selections <<< "mysql-server mysql-server/root_password_again password ${DBMS_PASSWORD}" + + # Install mysql + apt-get update -y + apt-get -y install mysql-server + + # Passwordless auth + cat < /root/.my.cnf + [client] + user=root + password=${DBMS_PASSWORD} + EOF + + # Listen on all interfaces + sed -i "s/127\.0\.0\.1/0\.0\.0\.0/g" /etc/mysql/mysql.conf.d/mysqld.cnf + + # Listen on custom port + sed -i "s/# port.*/port = ${DBMS_PORT}/g" /etc/mysql/mysql.conf.d/mysqld.cnf + + # Configure any host for root + mysql -u root -e 'USE mysql; UPDATE user SET host = "%" WHERE user = "root"; FLUSH PRIVILEGES;' + mysql -u root -e 'USE mysql; DELETE FROM user WHERE user = "root" and host = "localhost"; FLUSH PRIVILEGES;' + + # Enable service + systemctl enable mysql + + # Restart service + systemctl restart mysql + destination: /tmp/install-mysql-dbms.sh + remote-exec: + - inline: + - sudo bash /tmp/install-mysql-dbms.sh {{ SELF.dbms_password }} {{ SELF.application_port }} + mysql.dbms~software.application#apt.archive::terraform@*->remote.machine: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + DBMS_NAME="{{ SELF.dbms_name }}" + APPLICATION_NAME="{{ SELF.application_name }}" + DBMS_PASSWORD="{{ SELF.dbms_password }}" + DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-mysql.dbms {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-mysql.dbms.sh + remote-exec: + - inline: + - sudo bash /tmp/create-mysql.dbms.sh + - sudo bash /tmp/configure-mysql.dbms.sh + - sudo bash /tmp/start-mysql.dbms.sh + - inline: + - sudo bash /tmp/stop-mysql.dbms.sh + - sudo bash /tmp/delete-mysql.dbms.sh + when: destroy + mysql.dbms~software.application#tar.archive::terraform@*->remote.machine: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-mysql.dbms + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + DBMS_NAME="{{ SELF.dbms_name }}" + APPLICATION_NAME="{{ SELF.application_name }}" + DBMS_PASSWORD="{{ SELF.dbms_password }}" + DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-mysql.dbms {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-mysql.dbms -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-mysql.dbms.sh + remote-exec: + - inline: + - sudo bash /tmp/create-mysql.dbms.sh + - sudo bash /tmp/configure-mysql.dbms.sh + - sudo bash /tmp/start-mysql.dbms.sh + - inline: + - sudo bash /tmp/stop-mysql.dbms.sh + - sudo bash /tmp/delete-mysql.dbms.sh + when: destroy + mysql.dbms~software.application#zip.archive::terraform@*->remote.machine: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-mysql.dbms + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + DBMS_NAME="{{ SELF.dbms_name }}" + APPLICATION_NAME="{{ SELF.application_name }}" + DBMS_PASSWORD="{{ SELF.dbms_password }}" + DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-mysql.dbms {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-mysql.dbms -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-mysql.dbms.sh + remote-exec: + - inline: + - sudo bash /tmp/create-mysql.dbms.sh + - sudo bash /tmp/configure-mysql.dbms.sh + - sudo bash /tmp/start-mysql.dbms.sh + - inline: + - sudo bash /tmp/stop-mysql.dbms.sh + - sudo bash /tmp/delete-mysql.dbms.sh + when: destroy + mysql.dbms~mysql.dbms#dbms.image::kubernetes@kubernetes.cluster: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::dbms_name + application_port: + type: integer + default: 3306 + management_address: + type: string + default: + eval: .::application_address + management_port: + type: integer + default: + eval: .::application_port + interfaces: + Standard: + operations: + create: + 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: 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 }} rollout status deployment/{{ SELF.dbms_name }} --timeout 60s + args: + executable: /usr/bin/bash + - name: let it cook + ansible.builtin.pause: + seconds: 10 + 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->local.machine: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + application_port: + type: integer + default: 3306 + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: 3306 + capabilities: + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + interfaces: + Standard: + operations: + create: + 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: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} up -d + args: + executable: /usr/bin/bash + - name: let it cook + ansible.builtin.pause: + seconds: 10 + 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 + 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_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + application_port: + type: integer + default: 3306 + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: 3306 + capabilities: + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + interfaces: + Standard: + operations: + create: + 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: 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: let it cook + ansible.builtin.pause: + seconds: 10 + 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->local.machine: + derived_from: mysql.database + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: get dbms container info + community.docker.docker_container_info: + name: '{{ HOST.dbms_name }}' + register: dbms_container_info + - 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 + - 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 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - 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 + mysql.database~mysql.database::ansible@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: + type: string + default: + get_input: os_ssh_key_file + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install pip + apt: + name: python3-pip + state: present + - name: install pymysql + pip: + name: pymysql + state: present + - name: get dbms container info + community.docker.docker_container_info: + name: '{{ HOST.dbms_name }}' + register: dbms_container_info + - name: forward port + community.docker.docker_container: + name: '{{ HOST.dbms_name }}-port-forward' + image: nicolaka/netshoot:v0.13 + command: socat TCP6-LISTEN:3306,fork TCP:{{ HOST.dbms_name }}:3306 + ports: + - '{{ HOST.application_port }}:3306' + when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" + - name: create forwarding network + community.docker.docker_network: + name: '{{ HOST.dbms_name }}-port-forward' + connected: + - '{{ HOST.dbms_name }}-port-forward' + - '{{ HOST.dbms_name }}' + when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" + - 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 + - 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 + - name: unforward port + community.docker.docker_container: + name: '{{ HOST.dbms_name }}-port-forward' + image: nicolaka/netshoot:v0.13 + network_mode: host + state: absent + when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" + - name: remove forwarding network + community.docker.docker_network: + name: '{{ HOST.dbms_name }}-port-forward' + state: absent + when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: + - name: create a database + google.cloud.gcp_sql_database: + name: '{{ SELF.database_name }}' + charset: utf8 + instance: '{{ HOST.dbms_name }}' + project: '{{ SELF.gcp_project }}' + - name: install GCP CloudSQL Proxy + ansible.builtin.get_url: + url: https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.13.0/cloud-sql-proxy.linux.amd64 + dest: /tmp/gcp-cloudsql-proxy + mode: '0755' + - name: forward port + ansible.builtin.shell: '/tmp/gcp-cloudsql-proxy {{ SELF.gcp_project }}:{{ SELF.gcp_region }}:{{ HOST.dbms_name }} --credentials-file {{ SELF.gcp_service_account_file }} --port 23306 ' + args: + executable: /usr/bin/bash + async: 30 + poll: 0 + - name: wait for port + ansible.builtin.wait_for: + host: 127.0.0.1 + port: 23306 + delay: 5 + timeout: 30 + - name: create user (with privileges) + community.mysql.mysql_user: + name: '{{ SELF.database_user }}' + password: '{{ SELF.database_password }}' + host: '%' + priv: '*.*:ALL' + login_host: 127.0.0.1 + login_password: '{{ HOST.dbms_password }}' + login_port: 23306 + login_user: root + - name: unforward port + ansible.builtin.shell: pkill -f "/tmp/gcp-cloudsql-proxy {{ SELF.gcp_project }}:{{ SELF.gcp_region }}:{{ HOST.dbms_name }}" + args: + executable: /usr/bin/bash + mysql.database~mysql.database::ansible@mysql.dbms->kubernetes.cluster: + derived_from: mysql.database + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: deploy database + block: + - name: forward port + 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 + poll: 0 + - name: wait for port + ansible.builtin.wait_for: + host: 127.0.0.1 + port: 23306 + delay: 5 + timeout: 30 + - name: create database + community.mysql.mysql_db: + name: '{{ SELF.database_name }}' + login_host: 127.0.0.1 + login_password: '{{ HOST.dbms_password }}' + login_port: '23306' + login_user: root + - name: create user (with privileges) + community.mysql.mysql_user: + name: '{{ SELF.database_user }}' + password: '{{ SELF.database_password }}' + host: '%' + priv: '*.*:ALL' + login_host: 127.0.0.1 + login_password: '{{ HOST.dbms_password }}' + login_port: '23306' + login_user: root + always: + - name: unforward port + 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: + 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: + type: string + default: + get_input: os_ssh_key_file + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install pip + apt: + name: python3-pip + state: present + - name: install pymysql + pip: + name: pymysql + state: present + - 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 + - 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 + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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->local.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: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - mysql: + source: petoju/mysql + version: 3.0.48 + provider: + mysql: + - endpoint: 127.0.0.1:{{ HOST.management_port }} + password: '{{ HOST.dbms_password }}' + username: root + resource: + mysql_database: + database: + - name: '{{ SELF.database_name }}' + mysql_user: + user: + - host: '%' + plaintext_password: '{{ SELF.database_password }}' + user: '{{ SELF.database_user }}' + mysql_grant: + user: + - database: '{{ SELF.database_name }}' + host: '%' + table: '*' + privileges: + - ALL + user: ${mysql_user.user.user} + mysql.database~mysql.database::terraform@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: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - mysql: + source: petoju/mysql + version: 3.0.48 + ssh: + source: AndrewChubatiuk/ssh + version: 0.2.3 + data: + ssh_tunnel: + mysql: + - remote: + host: '{{ HOST.application_address }}' + port: '{{ HOST.application_port }}' + provider: + mysql: + - endpoint: ${data.ssh_tunnel.mysql.local.address} + password: '{{ HOST.dbms_password }}' + username: root + ssh: + - auth: + private_key: + content: ${file(pathexpand("{{ SELF.os_ssh_key_file }}"))} + server: + host: '{{ HOST.management_address }}' + port: 22 + user: '{{ SELF.os_ssh_user }}' + resource: + mysql_database: + database: + - name: '{{ SELF.database_name }}' + mysql_user: + user: + - host: '%' + plaintext_password: '{{ SELF.database_password }}' + user: '{{ SELF.database_user }}' + mysql_grant: + user: + - database: '{{ SELF.database_name }}' + host: '%' + table: '*' + privileges: + - ALL + user: ${mysql_user.user.user} + mysql.database~mysql.database::terraform@mysql.dbms->gcp.cloudsql: + derived_from: mysql.database + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + delete: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + mysql: + source: petoju/mysql + version: 3.0.48 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + mysql: + - endpoint: cloudsql://{{ SELF.gcp_project }}:{{ SELF.gcp_region }}:{{ HOST.dbms_name }} + password: '{{ HOST.dbms_password }}' + username: root + resource: + google_sql_database: + database: + - name: '{{ SELF.database_name }}' + instance: '{{ HOST.dbms_name }}' + google_sql_user: + user: + - host: '%' + instance: '{{ HOST.dbms_name }}' + name: '{{ SELF.database_name }}' + password: '{{ SELF.database_password }}' + mysql_grant: + user: + - database: '{{ SELF.database_name }}' + host: '%' + table: '*' + privileges: + - ALL + user: ${google_sql_user.user.name} + mysql.database~mysql.database::terraform@mysql.dbms->kubernetes.cluster: + derived_from: mysql.database + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - mysql: + source: petoju/mysql + version: 3.0.48 + provider: + mysql: + - endpoint: ${terraform_data.forward_port.input} + password: '{{ HOST.dbms_password }}' + username: root + resource: + terraform_data: + forward_port: + - input: 127.0.0.1:23306 + provisioner: + local-exec: + command: |- + (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 + - '-c' + unforward_port: + - depends_on: + - mysql_grant.user + provisioner: + local-exec: + command: pkill -f "port-forward service/{{ HOST.dbms_name }}" + interpreter: + - /bin/bash + - '-c' + mysql_database: + database: + - name: '{{ SELF.database_name }}' + mysql_user: + user: + - host: '%' + plaintext_password: '{{ SELF.database_password }}' + user: '{{ SELF.database_user }}' + mysql_grant: + user: + - database: '{{ SELF.database_name }}' + host: '%' + table: '*' + privileges: + - ALL + user: ${mysql_user.user.user} + mysql.database~mysql.database::terraform@mysql.dbms->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: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - mysql: + source: petoju/mysql + version: 3.0.48 + ssh: + source: AndrewChubatiuk/ssh + version: 0.2.3 + data: + ssh_tunnel: + mysql: + - remote: + host: '{{ HOST.application_address }}' + port: '{{ HOST.application_port }}' + provider: + mysql: + - endpoint: ${data.ssh_tunnel.mysql.local.address} + password: '{{ HOST.dbms_password }}' + username: root + ssh: + - auth: + private_key: + content: ${file(pathexpand("{{ SELF.os_ssh_key_file }}"))} + server: + host: '{{ HOST.management_address }}' + port: 22 + user: '{{ SELF.os_ssh_user }}' + resource: + mysql_database: + database: + - name: '{{ SELF.database_name }}' + mysql_user: + user: + - host: '%' + plaintext_password: '{{ SELF.database_password }}' + user: '{{ SELF.database_user }}' + mysql_grant: + user: + - database: '{{ SELF.database_name }}' + host: '%' + table: '*' + privileges: + - ALL + user: ${mysql_user.user.user} + mysql.database~mysql.database::kubernetes@mysql.dbms->kubernetes.cluster: + derived_from: mysql.database + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + interfaces: + Standard: + operations: + create: + 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 + - '--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 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 + - '--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 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 + mysql.database~mysql.database::compose@mysql.dbms->docker.engine->local.machine: + derived_from: mysql.database + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + interfaces: + Standard: + operations: + create: + 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' + - 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 + 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 + - 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 + 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_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + interfaces: + Standard: + operations: + create: + 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' + - 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 + 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 }}' + 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 }}' + minio.server~service.application#docker.image::ansible@docker.engine->local.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + minio.server~service.application#docker.image::ansible@docker.engine->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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 }}' + minio.server~service.application#docker.image::ansible@gcp.cloudrun: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: touch service + register: service + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.service.yaml' + - name: create service + ansible.builtin.copy: + dest: '{{ service.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + apiVersion: serving.knative.dev/v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + labels: + cloud.googleapis.com/location: '{{ SELF.gcp_region }}' + annotations: + run.googleapis.com/ingress: all + spec: + template: + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + containerPort: '{{ SELF.application_port }}' + env: [] + - name: apply service + ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet + args: + executable: /bin/bash + - name: touch policy + register: policy + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.policy.yaml' + - name: fill policy + ansible.builtin.copy: + dest: '{{ policy.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + bindings: + - members: + - allUsers + role: roles/run.invoker + - name: apply policy + ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + - name: describe service + register: service_description + ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + minio.server~service.application#docker.image::ansible@kubernetes.cluster: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: create deployment + kubernetes.core.k8s: + wait: true + definition: + 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 }}' + - name: create service + kubernetes.core.k8s: + definition: + 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 + 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 }}' + minio.server~service.application#tar.archive::ansible@*->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + minio.server~service.application#zip.archive::ansible@*->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + minio.server~service.application#zip.archive::ansible@gcp.appengine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: enable GCP AppEngine + ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + register: app_create_command + failed_when: + - "'Created' not in app_create_command.stderr" + - "'already contains' not in app_create_command.stderr" + - name: create working directory + register: directory + ansible.builtin.tempfile: + state: directory + - name: extract deployment artifact in working directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ directory.path }}' + - name: create specification + ansible.builtin.copy: + dest: '{{ directory.path }}/app.yaml' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + instance_class: F1 + env_variables: {} + - name: create app + ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet + args: + executable: /bin/bash + - name: browse app + register: browse_app + ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ browse_app.stdout[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet + args: + executable: /bin/bash + minio.server~software.application#apt.package::ansible@*->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + minio.server~software.application#tar.archive::ansible@*->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + minio.server~software.application#zip.archive::ansible@*->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + minio.server~service.application#docker.image::terraform@docker.engine->local.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + minio.server~service.application#docker.image::terraform@docker.engine->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + minio.server~service.application#docker.image::terraform@gcp.cloudrun: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' + resource: + google_cloud_run_v2_service: + application: + - ingress: INGRESS_TRAFFIC_ALL + location: '{{ SELF.gcp_region }}' + name: '{{ SELF.application_name }}' + template: + - containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + container_port: '{{ SELF.application_port }}' + env: [] + google_cloud_run_service_iam_binding: + application: + - location: '{{ SELF.gcp_region }}' + members: + - allUsers + role: roles/run.invoker + service: '{{ SELF.application_name }}' + minio.server~service.application#docker.image::terraform@kubernetes.cluster: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_deployment_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - selector: + - match_labels: + app: '{{ SELF.application_name }}' + template: + - metadata: + - labels: + app: '{{ SELF.application_name }}' + spec: + - container: + - env: [] + image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + port: + - container_port: '{{ SELF.application_port }}' + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - port: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + target_port: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + minio.server~service.application#tar.archive::terraform@*->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-minio.server + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-minio.server {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-minio.server -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-minio.server.sh + remote-exec: + - inline: + - sudo bash /tmp/create-minio.server.sh + - sudo bash /tmp/configure-minio.server.sh + - sudo bash /tmp/start-minio.server.sh + - inline: + - sudo bash /tmp/stop-minio.server.sh + - sudo bash /tmp/delete-minio.server.sh + when: destroy + minio.server~service.application#zip.archive::terraform@*->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-minio.server + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-minio.server {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-minio.server -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-minio.server.sh + remote-exec: + - inline: + - sudo bash /tmp/create-minio.server.sh + - sudo bash /tmp/configure-minio.server.sh + - sudo bash /tmp/start-minio.server.sh + - inline: + - sudo bash /tmp/stop-minio.server.sh + - sudo bash /tmp/delete-minio.server.sh + when: destroy + minio.server~service.application#zip.archive::terraform@gcp.appengine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' + resource: + google_app_engine_standard_app_version: + app: + - delete_service_on_destroy: true + deployment: + - zip: + - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} + entrypoint: + - shell: '{{ SELF._management_start }}' + env_variables: {} + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + service_account: ${google_service_account.custom_service_account.email} + version_id: v1 + google_project_iam_member: + gae_api: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/compute.networkUser + storage_viewer: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/storage.objectViewer + google_service_account: + custom_service_account: + - account_id: '{{ SELF.application_name }}-account' + display_name: Custom Service Account + google_storage_bucket: + bucket: + - location: EU + name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' + google_storage_bucket_object: + object: + - bucket: ${google_storage_bucket.bucket.name} + name: object.zip + source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + minio.server~software.application#apt.archive::terraform@*->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-minio.server {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-minio.server.sh + remote-exec: + - inline: + - sudo bash /tmp/create-minio.server.sh + - sudo bash /tmp/configure-minio.server.sh + - sudo bash /tmp/start-minio.server.sh + - inline: + - sudo bash /tmp/stop-minio.server.sh + - sudo bash /tmp/delete-minio.server.sh + when: destroy + minio.server~software.application#tar.archive::terraform@*->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-minio.server + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-minio.server {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-minio.server -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-minio.server.sh + remote-exec: + - inline: + - sudo bash /tmp/create-minio.server.sh + - sudo bash /tmp/configure-minio.server.sh + - sudo bash /tmp/start-minio.server.sh + - inline: + - sudo bash /tmp/stop-minio.server.sh + - sudo bash /tmp/delete-minio.server.sh + when: destroy + minio.server~software.application#zip.archive::terraform@*->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-minio.server + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-minio.server {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-minio.server -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-minio.server.sh + remote-exec: + - inline: + - sudo bash /tmp/create-minio.server.sh + - sudo bash /tmp/configure-minio.server.sh + - sudo bash /tmp/start-minio.server.sh + - inline: + - sudo bash /tmp/stop-minio.server.sh + - sudo bash /tmp/delete-minio.server.sh + when: destroy + minio.server~service.application#docker.image::kubernetes@kubernetes.cluster: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: 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 }} 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 + minio.server~service.application#docker.image::compose@docker.engine->local.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 + minio.server~service.application#docker.image::compose@docker.engine->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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 }}' + redis.server~redis.server#cache.image::ansible@docker.engine->local.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: + CACHE_NAME: '"{{ SELF.cache_name }}"' + CACHE_PORT: '"{{ SELF.cache_port }}"' + APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' + APPLICATION_NAME: '"{{ SELF.application_name }}"' + APPLICATION_PORT: '"{{ SELF.application_port }}"' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + redis.server~redis.server#cache.image::ansible@docker.engine->remote.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: + CACHE_NAME: '"{{ SELF.cache_name }}"' + CACHE_PORT: '"{{ SELF.cache_port }}"' + APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' + APPLICATION_NAME: '"{{ SELF.application_name }}"' + APPLICATION_PORT: '"{{ SELF.application_port }}"' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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 }}' + redis.server~redis.server::ansible@kubernetes.cluster: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + redis.server~software.application#apt.package::ansible@*->remote.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + redis.server~software.application#tar.archive::ansible@*->remote.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: |- + CACHE_NAME="{{ SELF.cache_name }}" + CACHE_PORT="{{ SELF.cache_port }}" + APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" + APPLICATION_NAME="{{ SELF.application_name }}" + APPLICATION_PORT="{{ SELF.application_port }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + redis.server~software.application#zip.archive::ansible@*->remote.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: |- + CACHE_NAME="{{ SELF.cache_name }}" + CACHE_PORT="{{ SELF.cache_port }}" + APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" + APPLICATION_NAME="{{ SELF.application_name }}" + APPLICATION_PORT="{{ SELF.application_port }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + redis.server~redis.server#cache.image::terraform@gcp.memorystore: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + delete: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + mysql: + source: petoju/mysql + version: 3.0.48 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + resource: {} + redis.server~redis.server#cache.image::terraform@docker.engine->local.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: + - CACHE_NAME={{ SELF.cache_name }} + - CACHE_PORT={{ SELF.cache_port }} + - APPLICATION_PROTOCOL={{ SELF.application_protocol }} + - APPLICATION_NAME={{ SELF.application_name }} + - APPLICATION_PORT={{ SELF.application_port }} + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + redis.server~redis.server#cache.image::terraform@docker.engine->remote.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - env: + - CACHE_NAME={{ SELF.cache_name }} + - CACHE_PORT={{ SELF.cache_port }} + - APPLICATION_PROTOCOL={{ SELF.application_protocol }} + - APPLICATION_NAME={{ SELF.application_name }} + - APPLICATION_PORT={{ SELF.application_port }} + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + redis.server~redis.server::terraform@kubernetes.cluster: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + delete: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + defaults: + inputs: + main: + terraform: [] + provider: {} + resource: {} + redis.server~software.application#apt.archive::terraform@*->remote.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + CACHE_NAME="{{ SELF.cache_name }}" + CACHE_PORT="{{ SELF.cache_port }}" + APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" + APPLICATION_NAME="{{ SELF.application_name }}" + APPLICATION_PORT="{{ SELF.application_port }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-redis.server {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-redis.server.sh + remote-exec: + - inline: + - sudo bash /tmp/create-redis.server.sh + - sudo bash /tmp/configure-redis.server.sh + - sudo bash /tmp/start-redis.server.sh + - inline: + - sudo bash /tmp/stop-redis.server.sh + - sudo bash /tmp/delete-redis.server.sh + when: destroy + redis.server~software.application#tar.archive::terraform@*->remote.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-redis.server + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + CACHE_NAME="{{ SELF.cache_name }}" + CACHE_PORT="{{ SELF.cache_port }}" + APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" + APPLICATION_NAME="{{ SELF.application_name }}" + APPLICATION_PORT="{{ SELF.application_port }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-redis.server {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-redis.server -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-redis.server.sh + remote-exec: + - inline: + - sudo bash /tmp/create-redis.server.sh + - sudo bash /tmp/configure-redis.server.sh + - sudo bash /tmp/start-redis.server.sh + - inline: + - sudo bash /tmp/stop-redis.server.sh + - sudo bash /tmp/delete-redis.server.sh + when: destroy + redis.server~software.application#zip.archive::terraform@*->remote.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-redis.server + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + CACHE_NAME="{{ SELF.cache_name }}" + CACHE_PORT="{{ SELF.cache_port }}" + APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" + APPLICATION_NAME="{{ SELF.application_name }}" + APPLICATION_PORT="{{ SELF.application_port }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-redis.server {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-redis.server -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-redis.server.sh + remote-exec: + - inline: + - sudo bash /tmp/create-redis.server.sh + - sudo bash /tmp/configure-redis.server.sh + - sudo bash /tmp/start-redis.server.sh + - inline: + - sudo bash /tmp/stop-redis.server.sh + - sudo bash /tmp/delete-redis.server.sh + when: destroy + redis.server~redis.server#cache.image::compose@docker.engine->local.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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: + CACHE_NAME: '"{{ SELF.cache_name }}"' + CACHE_PORT: '"{{ SELF.cache_port }}"' + APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' + APPLICATION_NAME: '"{{ SELF.application_name }}"' + APPLICATION_PORT: '"{{ SELF.application_port }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} up -d + args: + executable: /usr/bin/bash + 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: + CACHE_NAME: '"{{ SELF.cache_name }}"' + CACHE_PORT: '"{{ SELF.cache_port }}"' + APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' + APPLICATION_NAME: '"{{ SELF.application_name }}"' + APPLICATION_PORT: '"{{ SELF.application_port }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + redis.server~redis.server#cache.image::compose@docker.engine->remote.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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: + CACHE_NAME: '"{{ SELF.cache_name }}"' + CACHE_PORT: '"{{ SELF.cache_port }}"' + APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' + APPLICATION_NAME: '"{{ SELF.application_name }}"' + APPLICATION_PORT: '"{{ SELF.application_port }}"' + - 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 }}' + 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: + CACHE_NAME: '"{{ SELF.cache_name }}"' + CACHE_PORT: '"{{ SELF.cache_port }}"' + APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' + APPLICATION_NAME: '"{{ SELF.application_name }}"' + APPLICATION_PORT: '"{{ SELF.application_port }}"' + - 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---industry---plus-maintenance-automated/scripts/quality.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh index 640d86d97d..a1971f736c 100755 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh @@ -5,9 +5,4 @@ set -e source configuration.sh # Quality -#for dir in ../tests/*/; -for dir in "../tests/gcp"; -do - dir=$(basename $dir) - echo "${dir}: $($VINTNER template quality --template ${TEMPLATE_DIR}/variable-service-template.yaml --experimental --inputs ${TEMPLATE_DIR}/tests/${dir}/inputs.yaml)" -done +$VINTNER template quality --template ${TEMPLATE_DIR}/variable-service-template.yaml --experimental diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/study.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/study.yaml index 4b4ad8fb49..227ccb140c 100644 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/study.yaml +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/study.yaml @@ -1,6 +1,6 @@ study: technology originals: - - gcp - - kubernetes - - os-medium - - os-large + - customer + - development + - hyperscaler + - local diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/expected.yaml new file mode 100644 index 0000000000..7f3f0f125b --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/expected.yaml @@ -0,0 +1 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/inputs.yaml new file mode 100644 index 0000000000..7bf937ccc5 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/inputs.yaml @@ -0,0 +1 @@ +env: CUSTOMER diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/expected.yaml new file mode 100644 index 0000000000..7f3f0f125b --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/expected.yaml @@ -0,0 +1 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/inputs.yaml new file mode 100644 index 0000000000..09169fd274 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/inputs.yaml @@ -0,0 +1 @@ +env: DEVELOPMENT diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/expected.yaml deleted file mode 100644 index a72ce7bcf1..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/expected.yaml +++ /dev/null @@ -1,310 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_3 - -imports: - - lib/types.yaml - -topology_template: - inputs: - database_password: - type: string - - dbms_password: - type: string - - gcp_region: - type: string - - gcp_service_account_file: - type: string - - gcp_project: - type: string - - node_templates: - ################################################### - # - # Frontend - # - ################################################### - - frontend_component: - type: frontend.component~service.application#docker.image::terraform@gcp.cloudrun - properties: - application_name: frontend - application_port: 8080 - application_protocol: http - disable_profiler: '1' - CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} - CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} - SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} - CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} - PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} - RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} - AD_SERVICE_ADDR: {eval: '.::.requirements::[.name=advertisement]::.target::application_endpoint'} - optional_payment_feature: 'false' - premium_payment_feature: 'false' - SHOPPING_ASSISTANT_SERVICE_ADDR: 'required-but-not-used' - requirements: - - checkout: checkout_component - - currency: currency_component - - shipping: shipping_component - - cart: cart_component - - product: product_component - - recommendation: recommendation_component - - advertisement: advertisement_component - - host: gcp_cloudrun - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-frontend:v8 - - ################################################### - # - # Checkout - # - ################################################### - - checkout_component: - type: checkout.component~service.application#docker.image::terraform@gcp.cloudrun - properties: - application_name: checkout - application_port: 7003 - application_protocol: grpc - disable_profiler: '1' - PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} - SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} - PAYMENT_SERVICE_ADDR: {eval: '.::.requirements::[.name=payment]::.target::application_endpoint'} - EMAIL_SERVICE_ADDR: {eval: '.::.requirements::[.name=email]::.target::application_endpoint'} - CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} - CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} - optional_payment_feature: 'false' - premium_payment_feature: 'false' - requirements: - - email: email_component - - payment: payment_component - - currency: currency_component - - shipping: shipping_component - - cart: cart_component - - product: product_component - - host: gcp_cloudrun - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-checkout:v8 - - ################################################### - # - # Email - # - ################################################### - - email_component: - type: email.component~service.application#docker.image::terraform@gcp.cloudrun - properties: - application_name: email - application_port: 7005 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: gcp_cloudrun - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-email:v8 - - ################################################### - # - # Payment - # - ################################################### - - payment_component: - type: payment.component~service.application#docker.image::terraform@gcp.cloudrun - properties: - application_name: payment - application_port: 7006 - application_protocol: grpc - disable_profiler: '1' - optional_payment_feature: 'false' - premium_payment_feature: 'false' - requirements: - - host: gcp_cloudrun - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-payment:v8 - - ################################################### - # - # Currency - # - ################################################### - - currency_component: - type: currency.component~service.application#docker.image::terraform@gcp.cloudrun - properties: - application_name: currency - application_port: 7004 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: gcp_cloudrun - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-currency:v8 - - ################################################### - # - # Shipping - # - ################################################### - - shipping_component: - type: shipping.component~service.application#docker.image::terraform@gcp.cloudrun - properties: - application_name: shipping - application_port: 7009 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: gcp_cloudrun - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-shipping:v8 - - ################################################### - # - # Cart - # - ################################################### - - cart_component: - type: cart.component~service.application#docker.image::terraform@gcp.cloudrun - properties: - application_name: cart - application_port: 7070 - application_protocol: grpc - disable_profiler: '1' - mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} - mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} - mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} - mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} - mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} - mysql_table: 'cart' - mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} - - requirements: - - database: cart_database - - host: gcp_cloudrun - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-cart:v8 - - cart_database: - type: mysql.database~mysql.database::terraform@mysql.dbms->gcp.cloudsql - properties: - database_name: cart - database_user: cart - database_password: {get_input: database_password} - requirements: - - host: cart_dbms - - cart_dbms: - type: mysql.dbms~mysql.dbms#dbms.image::terraform@gcp.cloudsql - properties: - dbms_name: unfurl-technology-boutique-cart-dbms - dbms_password: {get_input: dbms_password} - requirements: - - host: gcp_cloudsql - artifacts: - dbms_image: - type: dbms.image - file: 5.7 - - ################################################### - # - # Product - # - ################################################### - - product_component: - type: product.component~service.application#docker.image::terraform@gcp.cloudrun - properties: - application_name: product - application_port: 7007 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: gcp_cloudrun - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-product:v8 - - ################################################### - # - # Recommendation - # - ################################################### - - recommendation_component: - type: recommendation.component~service.application#docker.image::terraform@gcp.cloudrun - properties: - application_name: recommendation - application_port: 7008 - application_protocol: grpc - disable_profiler: '1' - PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} - requirements: - - product: product_component - - host: gcp_cloudrun - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-recommendation:v8 - - ################################################### - # - # Advertisement - # - ################################################### - - advertisement_component: - type: advertisement.component~service.application#docker.image::terraform@gcp.cloudrun - properties: - application_name: advertisement - application_port: 7000 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: gcp_cloudrun - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-advertisement:v8 - - ################################################### - # - # GCP - # - ################################################### - - gcp_cloudrun: - type: gcp.cloudrun~gcp.service::terraform - requirements: - - host: gcp_provider - - gcp_cloudsql: - type: gcp.cloudsql~gcp.service::terraform - requirements: - - host: gcp_provider - - gcp_provider: - type: gcp.provider - properties: - gcp_region: {get_input: gcp_region} - gcp_service_account_file: {get_input: gcp_service_account_file} - gcp_project: {get_input: gcp_project} diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/inputs.yaml deleted file mode 100644 index f9aae7ddda..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/inputs.yaml +++ /dev/null @@ -1 +0,0 @@ -env: GCP diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/test.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/test.yaml deleted file mode 100644 index ec7309948d..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/gcp/test.yaml +++ /dev/null @@ -1,21 +0,0 @@ -merge: - topology_template: - node_templates: - analytics_component: - type: analytics.component~service.application#docker.image::terraform@gcp.cloudrun - properties: - application_name: analytics - application_port: 7001 - application_protocol: grpc - CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} - RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} - optional_analytical_feature: 'false' - premium_analytical_feature: 'false' - requirements: - - checkout: checkout_component - - recommendation: recommendation_component - - host: gcp_cloudrun - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-analytics:v8 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/expected.yaml new file mode 100644 index 0000000000..7f3f0f125b --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/expected.yaml @@ -0,0 +1 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/inputs.yaml new file mode 100644 index 0000000000..6fb22896df --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/inputs.yaml @@ -0,0 +1 @@ +env: HYPERSCALER diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/expected.yaml deleted file mode 100644 index aedf7cb34d..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/expected.yaml +++ /dev/null @@ -1,340 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_3 - -imports: - - lib/types.yaml - -topology_template: - inputs: - database_password: - type: string - - dbms_password: - type: string - - k8s_host: - type: string - - k8s_ca_cert_file: - type: string - - k8s_client_cert_file: - type: string - - k8s_client_key_file: - type: string - - node_templates: - ################################################### - # - # Frontend - # - ################################################### - - frontend_component: - type: frontend.component~service.application#docker.image::kubernetes@kubernetes.cluster - properties: - application_name: frontend - application_port: 8080 - application_protocol: http - disable_profiler: '1' - CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} - CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} - SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} - CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} - PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} - RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} - AD_SERVICE_ADDR: {eval: '.::.requirements::[.name=advertisement]::.target::application_endpoint'} - optional_payment_feature: 'false' - premium_payment_feature: 'false' - SHOPPING_ASSISTANT_SERVICE_ADDR: 'required-but-not-used' - requirements: - - checkout: checkout_component - - currency: currency_component - - shipping: shipping_component - - cart: cart_component - - product: product_component - - recommendation: recommendation_component - - advertisement: advertisement_component - - host: kubernetes_cluster - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-frontend:v8 - - frontend_ingress: - type: ingress~ingress::kubernetes@kubernetes.cluster - requirements: - - application: frontend_component - - host: kubernetes_cluster - - ################################################### - # - # Checkout - # - ################################################### - - checkout_component: - type: checkout.component~service.application#docker.image::kubernetes@kubernetes.cluster - properties: - application_name: checkout - application_port: 7003 - application_protocol: grpc - disable_profiler: '1' - PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} - SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} - PAYMENT_SERVICE_ADDR: {eval: '.::.requirements::[.name=payment]::.target::application_endpoint'} - EMAIL_SERVICE_ADDR: {eval: '.::.requirements::[.name=email]::.target::application_endpoint'} - CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} - CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} - optional_payment_feature: 'false' - premium_payment_feature: 'false' - requirements: - - email: email_component - - payment: payment_component - - currency: currency_component - - shipping: shipping_component - - cart: cart_component - - product: product_component - - host: kubernetes_cluster - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-checkout:v8 - - ################################################### - # - # Email - # - ################################################### - - email_component: - type: email.component~service.application#docker.image::kubernetes@kubernetes.cluster - properties: - application_name: email - application_port: 7005 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: kubernetes_cluster - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-email:v8 - - ################################################### - # - # Payment - # - ################################################### - - payment_component: - type: payment.component~service.application#docker.image::kubernetes@kubernetes.cluster - properties: - application_name: payment - application_port: 7006 - application_protocol: grpc - disable_profiler: '1' - optional_payment_feature: 'false' - premium_payment_feature: 'false' - requirements: - - host: kubernetes_cluster - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-payment:v8 - - ################################################### - # - # Currency - # - ################################################### - - currency_component: - type: currency.component~service.application#docker.image::kubernetes@kubernetes.cluster - properties: - application_name: currency - application_port: 7004 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: kubernetes_cluster - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-currency:v8 - - ################################################### - # - # Shipping - # - ################################################### - - shipping_component: - type: shipping.component~service.application#docker.image::kubernetes@kubernetes.cluster - properties: - application_name: shipping - application_port: 7009 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: kubernetes_cluster - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-shipping:v8 - - ################################################### - # - # Cart - # - ################################################### - - cart_component: - type: cart.component~service.application#docker.image::kubernetes@kubernetes.cluster - properties: - application_name: cart - application_port: 7070 - application_protocol: grpc - disable_profiler: '1' - mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} - mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} - mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} - mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} - mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} - mysql_table: 'cart' - mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} - - requirements: - - database: cart_database - - host: kubernetes_cluster - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-cart:v8 - - cart_database: - type: mysql.database~mysql.database::ansible@mysql.dbms->kubernetes.cluster - properties: - database_name: cart - database_user: cart - database_password: {get_input: database_password} - requirements: - - host: cart_dbms - - cart_dbms: - type: mysql.dbms~mysql.dbms#dbms.image::kubernetes@kubernetes.cluster - properties: - dbms_name: unfurl-technology-boutique-cart-dbms - dbms_password: {get_input: dbms_password} - requirements: - - host: kubernetes_cluster - artifacts: - dbms_image: - type: dbms.image - file: 5.7 - - ################################################### - # - # Product - # - ################################################### - - product_component: - type: product.component~service.application#docker.image::kubernetes@kubernetes.cluster - properties: - application_name: product - application_port: 7007 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: kubernetes_cluster - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-product:v8 - - ################################################### - # - # Recommendation - # - ################################################### - - recommendation_component: - type: recommendation.component~service.application#docker.image::kubernetes@kubernetes.cluster - properties: - application_name: recommendation - application_port: 7008 - application_protocol: grpc - disable_profiler: '1' - PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} - requirements: - - product: product_component - - host: kubernetes_cluster - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-recommendation:v8 - - ################################################### - # - # Advertisement - # - ################################################### - - advertisement_component: - type: advertisement.component~service.application#docker.image::kubernetes@kubernetes.cluster - properties: - application_name: advertisement - application_port: 7000 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: kubernetes_cluster - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-advertisement:v8 - - ################################################### - # - # Analytical - # - ################################################### - - analytics_component: - type: analytics.component~service.application#docker.image::kubernetes@kubernetes.cluster - properties: - application_name: analytics - application_port: 7001 - application_protocol: grpc - CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} - RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} - optional_analytical_feature: 'false' - premium_analytical_feature: 'false' - requirements: - - checkout: checkout_component - - recommendation: recommendation_component - - host: kubernetes_cluster - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-analytics:v8 - - ################################################### - # - # Kubernetes - # - ################################################### - - kubernetes_cluster: - type: kubernetes.cluster - properties: - k8s_host: {get_input: k8s_host} - k8s_ca_cert_file: {get_input: k8s_ca_cert_file} - k8s_client_cert_file: {get_input: k8s_client_cert_file} - k8s_client_key_file: {get_input: k8s_client_key_file} - requirements: - - host: kubernetes_provider - - kubernetes_provider: - type: cloud.provider diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/inputs.yaml deleted file mode 100644 index efdff7c51b..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/kubernetes/inputs.yaml +++ /dev/null @@ -1 +0,0 @@ -env: KUBERNETES diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/expected.yaml new file mode 100644 index 0000000000..7f3f0f125b --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/expected.yaml @@ -0,0 +1 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/inputs.yaml new file mode 100644 index 0000000000..4988a41091 --- /dev/null +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/inputs.yaml @@ -0,0 +1 @@ +env: LOCAL diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/expected.yaml deleted file mode 100644 index e96254d028..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/expected.yaml +++ /dev/null @@ -1,402 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_3 - -imports: - - lib/types.yaml - -topology_template: - inputs: - database_password: - type: string - - dbms_password: - type: string - - os_network: - type: string - - os_ssh_key_name: - type: string - - os_ssh_user: - type: string - - os_ssh_key_file: - type: string - - os_region_name: - type: string - - os_auth_type: - type: string - - os_auth_url: - type: string - - os_identity_api_version: - type: string - - os_interface: - type: string - - os_application_credential_id: - type: string - - os_application_credential_secret: - type: string - - node_templates: - ################################################### - # - # Frontend - # - ################################################### - - frontend_component: - type: frontend.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: frontend - application_port: 8080 - application_protocol: http - disable_profiler: '1' - CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} - CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} - SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} - CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} - PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} - RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} - AD_SERVICE_ADDR: {eval: '.::.requirements::[.name=advertisement]::.target::application_endpoint'} - optional_payment_feature: 'false' - premium_payment_feature: 'false' - SHOPPING_ASSISTANT_SERVICE_ADDR: 'required-but-not-used' - requirements: - - checkout: checkout_component - - currency: currency_component - - shipping: shipping_component - - cart: cart_component - - product: product_component - - recommendation: recommendation_component - - advertisement: advertisement_component - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-frontend:v8 - - frontend_ingress: - type: ingress~ingress::ansible@remote.machine - requirements: - - application: frontend_component - - host: virtual_machine - - ################################################### - # - # Checkout - # - ################################################### - - checkout_component: - type: checkout.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: checkout - application_port: 7003 - application_protocol: grpc - disable_profiler: '1' - PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} - SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} - PAYMENT_SERVICE_ADDR: {eval: '.::.requirements::[.name=payment]::.target::application_endpoint'} - EMAIL_SERVICE_ADDR: {eval: '.::.requirements::[.name=email]::.target::application_endpoint'} - CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} - CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} - optional_payment_feature: 'false' - premium_payment_feature: 'false' - requirements: - - email: email_component - - payment: payment_component - - currency: currency_component - - shipping: shipping_component - - cart: cart_component - - product: product_component - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-checkout:v8 - - ################################################### - # - # Email - # - ################################################### - - email_component: - type: email.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: email - application_port: 7005 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-email:v8 - - ################################################### - # - # Payment - # - ################################################### - - payment_component: - type: payment.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: payment - application_port: 7006 - application_protocol: grpc - disable_profiler: '1' - optional_payment_feature: 'false' - premium_payment_feature: 'false' - requirements: - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-payment:v8 - - ################################################### - # - # Currency - # - ################################################### - - currency_component: - type: currency.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: currency - application_port: 7004 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-currency:v8 - - ################################################### - # - # Shipping - # - ################################################### - - shipping_component: - type: shipping.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: shipping - application_port: 7009 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-shipping:v8 - - ################################################### - # - # Cart - # - ################################################### - - cart_component: - type: cart.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: cart - application_port: 7070 - application_protocol: grpc - disable_profiler: '1' - mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} - mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} - mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} - mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} - mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} - mysql_table: 'cart' - mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} - requirements: - - database: cart_database - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-cart:v8 - - cart_database: - type: mysql.database~mysql.database::ansible@mysql.dbms->docker.engine->remote.machine - properties: - database_name: cart - database_user: cart - database_password: {get_input: database_password} - requirements: - - host: cart_dbms - - cart_dbms: - type: mysql.dbms~mysql.dbms#dbms.image::compose@docker.engine->remote.machine - properties: - dbms_name: unfurl-technology-boutique-cart-dbms - dbms_password: {get_input: dbms_password} - requirements: - - host: docker_engine - artifacts: - dbms_image: - type: dbms.image - file: 5.7 - - ################################################### - # - # Product - # - ################################################### - - product_component: - type: product.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: product - application_port: 7007 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-product:v8 - - ################################################### - # - # Recommendation - # - ################################################### - - recommendation_component: - type: recommendation.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: recommendation - application_port: 7008 - application_protocol: grpc - disable_profiler: '1' - PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} - requirements: - - product: product_component - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-recommendation:v8 - - ################################################### - # - # Advertisement - # - ################################################### - - advertisement_component: - type: advertisement.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: advertisement - application_port: 7000 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-advertisement:v8 - - ################################################### - # - # Virtual Machine - # - ################################################### - - docker_engine: - type: docker.engine~docker.engine::ansible@remote.machine - requirements: - - host: virtual_machine - - node_agent: - type: node.agent~service.application#tar.archive::ansible@*->remote.machine - properties: - application_name: node_exporter - application_port: 9100 - application_protocol: http - requirements: - - host: virtual_machine - artifacts: - tar_archive: - type: tar.archive - file: https://github.com/prometheus/node_exporter/releases/download/v1.6.0/node_exporter-1.6.0.linux-amd64.tar.gz - properties: - extra_opts: - - '--strip-components=1' - - promtail_agent: - type: promtail.agent~software.application#apt.package::ansible@*->remote.machine - properties: - application_name: promtail - requirements: - - host: virtual_machine - artifacts: - apt_package: - type: apt.package - file: promtail - properties: - repository: grafana - key: https://apt.grafana.com/gpg.key - source: https://apt.grafana.com stable main - - falco_agent: - type: falco.agent~software.application#apt.package::ansible@*->remote.machine - properties: - application_name: falco - requirements: - - host: virtual_machine - artifacts: - apt_package: - type: apt.package - file: falco - properties: - repository: falco - key: https://falco.org/repo/falcosecurity-packages.asc - source: https://download.falco.org/packages/deb stable main - env: FALCO_FRONTEND=noninteractive - - virtual_machine: - type: virtual.machine~virtual.machine#machine.image::terraform@openstack.provider - properties: - machine_name: unfurl-technology-boutique - ports: ['80', '2375', '9100'] - flavor: m1.large - network: {get_input: os_network} - ssh_key_name: {get_input: os_ssh_key_name} - ssh_user: {get_input: os_ssh_user} - ssh_key_file: {get_input: os_ssh_key_file} - requirements: - - host: openstack_provider - artifacts: - machine_image: - type: machine.image - file: Ubuntu 22.04 - - openstack_provider: - type: openstack.provider - properties: - os_region_name: {get_input: os_region_name} - os_auth_type: {get_input: os_auth_type} - os_auth_url: {get_input: os_auth_url} - os_identity_api_version: {get_input: os_identity_api_version} - os_interface: {get_input: os_interface} - os_application_credential_id: {get_input: os_application_credential_id} - os_application_credential_secret: {get_input: os_application_credential_secret} diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/inputs.yaml deleted file mode 100644 index 788bbd80c0..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/inputs.yaml +++ /dev/null @@ -1,2 +0,0 @@ -env: OPENSTACK -tier: LARGE diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/test.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/test.yaml deleted file mode 100644 index 616f52519b..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-large/test.yaml +++ /dev/null @@ -1,21 +0,0 @@ -merge: - topology_template: - node_templates: - analytics_component: - type: analytics.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: analytics - application_port: 7001 - application_protocol: grpc - CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} - RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} - optional_analytical_feature: 'false' - premium_analytical_feature: 'false' - requirements: - - checkout: checkout_component - - recommendation: recommendation_component - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-analytics:v8 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/expected.yaml deleted file mode 100644 index f92e8eed41..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/expected.yaml +++ /dev/null @@ -1,402 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_3 - -imports: - - lib/types.yaml - -topology_template: - inputs: - database_password: - type: string - - dbms_password: - type: string - - os_network: - type: string - - os_ssh_key_name: - type: string - - os_ssh_user: - type: string - - os_ssh_key_file: - type: string - - os_region_name: - type: string - - os_auth_type: - type: string - - os_auth_url: - type: string - - os_identity_api_version: - type: string - - os_interface: - type: string - - os_application_credential_id: - type: string - - os_application_credential_secret: - type: string - - node_templates: - ################################################### - # - # Frontend - # - ################################################### - - frontend_component: - type: frontend.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: frontend - application_port: 8080 - application_protocol: http - disable_profiler: '1' - CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} - CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} - SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} - CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} - PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} - RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} - AD_SERVICE_ADDR: {eval: '.::.requirements::[.name=advertisement]::.target::application_endpoint'} - optional_payment_feature: 'false' - premium_payment_feature: 'false' - SHOPPING_ASSISTANT_SERVICE_ADDR: 'required-but-not-used' - requirements: - - checkout: checkout_component - - currency: currency_component - - shipping: shipping_component - - cart: cart_component - - product: product_component - - recommendation: recommendation_component - - advertisement: advertisement_component - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-frontend:v8 - - frontend_ingress: - type: ingress~ingress::ansible@remote.machine - requirements: - - application: frontend_component - - host: virtual_machine - - ################################################### - # - # Checkout - # - ################################################### - - checkout_component: - type: checkout.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: checkout - application_port: 7003 - application_protocol: grpc - disable_profiler: '1' - PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} - SHIPPING_SERVICE_ADDR: {eval: '.::.requirements::[.name=shipping]::.target::application_endpoint'} - PAYMENT_SERVICE_ADDR: {eval: '.::.requirements::[.name=payment]::.target::application_endpoint'} - EMAIL_SERVICE_ADDR: {eval: '.::.requirements::[.name=email]::.target::application_endpoint'} - CURRENCY_SERVICE_ADDR: {eval: '.::.requirements::[.name=currency]::.target::application_endpoint'} - CART_SERVICE_ADDR: {eval: '.::.requirements::[.name=cart]::.target::application_endpoint'} - optional_payment_feature: 'false' - premium_payment_feature: 'false' - requirements: - - email: email_component - - payment: payment_component - - currency: currency_component - - shipping: shipping_component - - cart: cart_component - - product: product_component - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-checkout:v8 - - ################################################### - # - # Email - # - ################################################### - - email_component: - type: email.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: email - application_port: 7005 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-email:v8 - - ################################################### - # - # Payment - # - ################################################### - - payment_component: - type: payment.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: payment - application_port: 7006 - application_protocol: grpc - disable_profiler: '1' - optional_payment_feature: 'false' - premium_payment_feature: 'false' - requirements: - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-payment:v8 - - ################################################### - # - # Currency - # - ################################################### - - currency_component: - type: currency.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: currency - application_port: 7004 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-currency:v8 - - ################################################### - # - # Shipping - # - ################################################### - - shipping_component: - type: shipping.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: shipping - application_port: 7009 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-shipping:v8 - - ################################################### - # - # Cart - # - ################################################### - - cart_component: - type: cart.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: cart - application_port: 7070 - application_protocol: grpc - disable_profiler: '1' - mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} - mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} - mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} - mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} - mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} - mysql_table: 'cart' - mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} - requirements: - - database: cart_database - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-cart:v8 - - cart_database: - type: mysql.database~mysql.database::ansible@mysql.dbms->docker.engine->remote.machine - properties: - database_name: cart - database_user: cart - database_password: {get_input: database_password} - requirements: - - host: cart_dbms - - cart_dbms: - type: mysql.dbms~mysql.dbms#dbms.image::compose@docker.engine->remote.machine - properties: - dbms_name: unfurl-technology-boutique-cart-dbms - dbms_password: {get_input: dbms_password} - requirements: - - host: docker_engine - artifacts: - dbms_image: - type: dbms.image - file: 5.7 - - ################################################### - # - # Product - # - ################################################### - - product_component: - type: product.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: product - application_port: 7007 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-product:v8 - - ################################################### - # - # Recommendation - # - ################################################### - - recommendation_component: - type: recommendation.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: recommendation - application_port: 7008 - application_protocol: grpc - disable_profiler: '1' - PRODUCT_CATALOG_SERVICE_ADDR: {eval: '.::.requirements::[.name=product]::.target::application_endpoint'} - requirements: - - product: product_component - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-recommendation:v8 - - ################################################### - # - # Advertisement - # - ################################################### - - advertisement_component: - type: advertisement.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: advertisement - application_port: 7000 - application_protocol: grpc - disable_profiler: '1' - requirements: - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-advertisement:v8 - - ################################################### - # - # Virtual Machine - # - ################################################### - - docker_engine: - type: docker.engine~docker.engine::ansible@remote.machine - requirements: - - host: virtual_machine - - node_agent: - type: node.agent~service.application#tar.archive::ansible@*->remote.machine - properties: - application_name: node_exporter - application_port: 9100 - application_protocol: http - requirements: - - host: virtual_machine - artifacts: - tar_archive: - type: tar.archive - file: https://github.com/prometheus/node_exporter/releases/download/v1.6.0/node_exporter-1.6.0.linux-amd64.tar.gz - properties: - extra_opts: - - '--strip-components=1' - - promtail_agent: - type: promtail.agent~software.application#apt.package::ansible@*->remote.machine - properties: - application_name: promtail - requirements: - - host: virtual_machine - artifacts: - apt_package: - type: apt.package - file: promtail - properties: - repository: grafana - key: https://apt.grafana.com/gpg.key - source: https://apt.grafana.com stable main - - falco_agent: - type: falco.agent~software.application#apt.package::ansible@*->remote.machine - properties: - application_name: falco - requirements: - - host: virtual_machine - artifacts: - apt_package: - type: apt.package - file: falco - properties: - repository: falco - key: https://falco.org/repo/falcosecurity-packages.asc - source: https://download.falco.org/packages/deb stable main - env: FALCO_FRONTEND=noninteractive - - virtual_machine: - type: virtual.machine~virtual.machine#machine.image::terraform@openstack.provider - properties: - machine_name: unfurl-technology-boutique - ports: ['80', '2375', '9100'] - flavor: m1.medium - network: {get_input: os_network} - ssh_key_name: {get_input: os_ssh_key_name} - ssh_user: {get_input: os_ssh_user} - ssh_key_file: {get_input: os_ssh_key_file} - requirements: - - host: openstack_provider - artifacts: - machine_image: - type: machine.image - file: Ubuntu 22.04 - - openstack_provider: - type: openstack.provider - properties: - os_region_name: {get_input: os_region_name} - os_auth_type: {get_input: os_auth_type} - os_auth_url: {get_input: os_auth_url} - os_identity_api_version: {get_input: os_identity_api_version} - os_interface: {get_input: os_interface} - os_application_credential_id: {get_input: os_application_credential_id} - os_application_credential_secret: {get_input: os_application_credential_secret} diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/inputs.yaml deleted file mode 100644 index 3070bec9b6..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/inputs.yaml +++ /dev/null @@ -1,2 +0,0 @@ -env: OPENSTACK -tier: MEDIUM diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/test.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/test.yaml deleted file mode 100644 index 616f52519b..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/os-medium/test.yaml +++ /dev/null @@ -1,21 +0,0 @@ -merge: - topology_template: - node_templates: - analytics_component: - type: analytics.component~service.application#docker.image::compose@docker.engine->remote.machine - properties: - application_name: analytics - application_port: 7001 - application_protocol: grpc - CHECKOUT_SERVICE_ADDR: {eval: '.::.requirements::[.name=checkout]::.target::application_endpoint'} - RECOMMENDATION_SERVICE_ADDR: {eval: '.::.requirements::[.name=recommendation]::.target::application_endpoint'} - optional_analytical_feature: 'false' - premium_analytical_feature: 'false' - requirements: - - checkout: checkout_component - - recommendation: recommendation_component - - host: docker_engine - artifacts: - docker_image: - type: docker.image - file: milesstoetzner/boutique-analytics:v8 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml index 24afc30629..33520b274e 100644 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml @@ -88,8 +88,8 @@ topology_template: variability: expressions: - has_info_logging: {equal: [{variability_input: ERROR}, true]} - has_debug_logging: {equal: [{variability_input: DEBUG}, true]} + has_info_logging: {equal: [{variability_input: logging}, ERROR]} + has_debug_logging: {equal: [{variability_input: logging}, DEBUG]} has_error_masking: {equal: [{variability_input: errors}, true]} has_coffee: {equal: [{variability_input: coffee}, true]} @@ -98,47 +98,63 @@ topology_template: has_playground: {equal: [{variability_input: playground}, true]} has_import: {equal: [{variability_input: import}, true]} - has_import_schema_a: {equal: [{variability_input: import_schema_a}, A]} - has_import_schema_b: {equal: [{variability_input: import_schema_b}, B]} + has_import_schema_a: {equal: [{variability_input: import_schema}, A]} + has_import_schema_b: {equal: [{variability_input: import_schema}, B]} has_payment_merchant_a: {equal: [{variability_input: payment_merchant_a}, true]} has_payment_merchant_b: {equal: [{variability_input: payment_merchant_b}, true]} - is_gcp: {equal: [{variability_input: env}, GCP]} + is_hyperscaler: {equal: [{variability_input: env}, HYPERSCALER]} is_local: {equal: [{variability_input: env}, LOCAL]} is_customer: {equal: [{variability_input: env}, CUSTOMER]} - is_openstack: {equal: [{variability_input: env}, OPENSTACK]} + is_development: {equal: [{variability_input: env}, DEVELOPMENT]} + + # TODO: remove these + options: + technology_constraint: false + required_artifact_constraint: false + required_incoming_relation_constraint: false + inputs: env: type: string - default: OPENSTACK + default: DEVELOPMENT errors: type: boolean + default: false logging: type: string + default: INFO coffee: type: boolean + default: false introspection: type: boolean + default: false playground: type: boolean + default: false import: type: boolean + default: false import_schema: type: string + default: A payment_merchant_a: type: boolean + default: true payment_merchant_b: type: boolean + default: true node_templates: ################################################### @@ -245,11 +261,11 @@ topology_template: - has_error_masking: value: true - conditions: {logic_expression: has_errors} + conditions: {logic_expression: has_error_masking} - has_error_masking: value: false - conditions: {not: {logic_expression: has_errors}} + conditions: {not: {logic_expression: has_error_masking}} - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} - retailer_service_core_endpoint: {eval: '.::.requirements::[.name=retailer_service_core]::.target::application_endpoint'} @@ -275,6 +291,7 @@ topology_template: type: docker.image file: retailer.service.gateway:vX.Y.Z + # TODO: frontends brauchen auch ingressessesesss retailer_gateway_ingress: type: ingress requirements: @@ -438,14 +455,14 @@ topology_template: requirements: - host: retailer_dbms - # TODO: needs implementations + # TODO: is missing implementation if minio is hosted on k8s retailer_bucket_stores: type: bucket properties: - bucket_name: stores - bucket_dialect: value: minio - conditions: {node_presence: minio} + conditions: {node_presence: retailer_minio} - bucket_dialect: value: gcp @@ -531,7 +548,7 @@ topology_template: - bucket_name: products - bucket_dialect: value: minio - conditions: {node_presence: minio} + conditions: {node_presence: retailer_minio} - bucket_dialect: value: gcp @@ -685,6 +702,7 @@ topology_template: - host: local_docker_engine - host: remote_docker_engine - host: kubernetes_cluster + - host: gcp_cloudsql artifacts: - dbms_image: type: dbms.image @@ -699,17 +717,20 @@ topology_template: retailer_cache_redis: type: redis.server properties: - - application_name: retailer-cache-redis - - application_port: 6379 - - application_protocol: redis + - cache_name: retailer-cache-redis + - cache_port: 6379 requirements: - host: local_docker_engine - host: remote_docker_engine - - host: kubernetes_cluster + - host: gcp_memorystore + - host: + node: kubernetes_cluster + # TODO: this might not be required + conditions: {logic_expression: is_customer} artifacts: - - docker_image: - type: docker.image - file: redis:7.4.0 + - cache_image: + type: cache.image + file: 7.4.0 ################################################### # @@ -719,6 +740,8 @@ topology_template: retailer_minio: type: minio.server + # TODO: remove this? but complains about ambiguous in when hyperscaler + conditions: {not: {logic_expression: is_hyperscaler}} properties: - application_name: retailer-minio-server - application_port: 9000 @@ -726,9 +749,7 @@ topology_template: requirements: - host: local_docker_engine - host: remote_docker_engine - - host: - node: kubernetes_cluster - conditions: {logic_expression: is_customer} + - host: kubernetes_cluster artifacts: - docker_image: type: docker.image @@ -740,8 +761,6 @@ topology_template: # ################################################### - # TODO: handle local docker engine: we do not deploy the docker engine, but assumed its already installed. we might ping it to verify it! - # TODO: handle applications hosted on local docker engine local_docker_engine: type: docker.engine requirements: @@ -749,6 +768,7 @@ topology_template: local_machine: type: local.machine + conditions: {logic_expression: is_local} ################################################### # @@ -766,12 +786,7 @@ topology_template: properties: - machine_name: unfurl-technology-boutique - ports: ['80', '2375', '9100'] - - flavor: - value: m1.medium - conditions: {equal: [{variability_input: tier}, MEDIUM]} - - flavor: - value: m1.large - conditions: {equal: [{variability_input: tier}, LARGE]} + - flavor: m1.medium - network: {get_input: os_network} - ssh_user: {get_input: os_ssh_user} - ssh_key_name: {get_input: os_ssh_key_name} @@ -785,7 +800,7 @@ topology_template: openstack_provider: type: openstack.provider - conditions: {logic_expression: is_openstack} + conditions: {logic_expression: is_development} properties: - os_region_name: {get_input: os_region_name} - os_auth_type: {get_input: os_auth_type} @@ -801,6 +816,11 @@ topology_template: # ################################################### + gcp_memorystore: + type: gcp.memorystore + requirements: + - host: gcp_provider + gcp_kubernetesengine: type: gcp.kubernetesengine requirements: @@ -823,7 +843,7 @@ topology_template: gcp_provider: type: gcp.provider - conditions: {logic_expression: is_gcp} + conditions: {logic_expression: is_hyperscaler} properties: - gcp_region: {get_input: gcp_region} - gcp_service_account_file: {get_input: gcp_service_account_file} diff --git a/src/normative/dialects/unfurl/extended/nodes.ts b/src/normative/dialects/unfurl/extended/nodes.ts index 98b956bb36..7db1f861e1 100644 --- a/src/normative/dialects/unfurl/extended/nodes.ts +++ b/src/normative/dialects/unfurl/extended/nodes.ts @@ -103,6 +103,20 @@ const nodes: RecursivePartial = { }, }, }, + 'redis.server': { + properties: { + application_name: { + default: { + eval: '.::cache_name', + }, + }, + application_port: { + default: { + eval: '.::cache_port', + }, + }, + }, + }, } export default nodes diff --git a/src/normative/types/core/artifacts.ts b/src/normative/types/core/artifacts.ts index bcfce54c46..bb497ee608 100644 --- a/src/normative/types/core/artifacts.ts +++ b/src/normative/types/core/artifacts.ts @@ -83,6 +83,13 @@ const artifacts: ArtifactTypeMap = { ...MetadataNormative(), }, }, + 'cache.image': { + derived_from: 'artifact', + description: 'expects image reference in "file"', + metadata: { + ...MetadataNormative(), + }, + }, } export default artifacts diff --git a/src/normative/types/core/nodes.ts b/src/normative/types/core/nodes.ts index fe65ba56d0..d61a86da0d 100644 --- a/src/normative/types/core/nodes.ts +++ b/src/normative/types/core/nodes.ts @@ -125,11 +125,20 @@ const nodes: NodeTypeMap = { type: 'string', }, }, + attributes: { + application_address: { + type: 'string', + }, + management_address: { + type: 'string', + }, + }, }, 'local.machine': { derived_from: 'machine', metadata: { ...MetadataNormative(), + ...MetadataAbstract(), }, capabilities: { host: { @@ -169,14 +178,6 @@ const nodes: NodeTypeMap = { type: 'string', }, }, - attributes: { - management_address: { - type: 'string', - }, - application_address: { - type: 'string', - }, - }, capabilities: { host: { type: 'tosca.capabilities.Compute', diff --git a/src/normative/types/extended/nodes.ts b/src/normative/types/extended/nodes.ts index 267ea7ff87..7110eb2368 100644 --- a/src/normative/types/extended/nodes.ts +++ b/src/normative/types/extended/nodes.ts @@ -375,6 +375,18 @@ const nodes: NodeTypeMap = { }, }, }, + 'gcp.memorystore': { + derived_from: 'gcp.service', + metadata: { + ...MetadataNormative(), + }, + properties: { + gcp_service: { + type: 'string', + default: 'redis.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', @@ -569,10 +581,28 @@ const nodes: NodeTypeMap = { ], }, 'minio.server': { - derived_from: 'software.application', + derived_from: 'service.application', + metadata: { + ...MetadataNormative(), + }, }, 'redis.server': { derived_from: 'cache', + metadata: { + ...MetadataNormative(), + }, + properties: { + cache_name: { + type: 'string', + }, + cache_port: { + type: 'string', + }, + application_protocol: { + type: 'string', + default: 'redis', + }, + }, }, } diff --git a/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts b/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts new file mode 100644 index 0000000000..4688a24cf8 --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts @@ -0,0 +1,71 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleOrchestratorOperation, + GCPProviderCredentials, + MetadataGenerated, + MetadataUnfurl, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this, see https://docs.ansible.com/ansible/latest/collections/google/cloud/gcp_storage_object_module.html + +const generator: ImplementationGenerator = { + component: 'bucket', + technology: 'ansible', + hosting: ['gcp.cloudstorage'], + // TODO: which weight? most likely 1 + weight: 0.5, + reason: 'Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this.', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...GCPProviderCredentials(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + environment: { + GCP_SERVICE_ACCOUNT_FILE: { + eval: '.::gcp_service_account_file', + }, + GCP_AUTH_KIND: 'serviceaccount', + }, + }, + inputs: { + playbook: { + q: [], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + environment: { + GCP_SERVICE_ACCOUNT_FILE: { + eval: '.::gcp_service_account_file', + }, + GCP_AUTH_KIND: 'serviceaccount', + }, + }, + inputs: { + playbook: { + q: [], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/index.ts b/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/index.ts new file mode 100644 index 0000000000..c76a810960 --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/index.ts @@ -0,0 +1,4 @@ +import ansible from './ansible' +import terraform from './terraform' + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/terraform/index.ts b/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/terraform/index.ts new file mode 100644 index 0000000000..9822275c38 --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/terraform/index.ts @@ -0,0 +1,72 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + GCPProviderCredentials, + MetadataGenerated, + MetadataUnfurl, + TerraformStandardOperations, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this, see https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket + +const generator: ImplementationGenerator = { + component: 'bucket', + technology: 'terraform', + hosting: ['gcp.cloudstorage'], + weight: 1, + reason: 'Terraform provides a declarative module.', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...GCPProviderCredentials(), + }, + + interfaces: { + ...TerraformStandardOperations({ + GOOGLE_APPLICATION_CREDENTIALS: { + eval: '.::gcp_service_account_file', + }, + }), + defaults: { + inputs: { + main: { + terraform: [ + { + required_providers: [ + { + google: { + source: 'hashicorp/google', + version: '5.39.1', + }, + mysql: { + source: 'petoju/mysql', + version: '3.0.48', + }, + }, + ], + }, + ], + provider: { + google: [ + { + credentials: '{{ SELF.gcp_service_account_file }}', + project: '{{ SELF.gcp_project }}', + region: '{{ SELF.gcp_region }}', + }, + ], + }, + resource: {}, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/bucket/index.ts b/src/technologies/plugins/rules/generators/bucket/index.ts new file mode 100644 index 0000000000..88fc439938 --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/index.ts @@ -0,0 +1,4 @@ +import gcpCloudStorage from './gcp-cloudstorage' +import minIO from './minio' + +export default [gcpCloudStorage, minIO] diff --git a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/index.ts new file mode 100644 index 0000000000..1fd9f3e86c --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/index.ts @@ -0,0 +1,4 @@ +import localMachine from './local-machine' +import remoteMachine from './remote-machine' + +export default [localMachine, remoteMachine] diff --git a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/ansible/index.ts new file mode 100644 index 0000000000..ab92c9c51f --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/ansible/index.ts @@ -0,0 +1,59 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleOrchestratorOperation, + GCPProviderCredentials, + MetadataGenerated, + MetadataUnfurl, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this + +const generator: ImplementationGenerator = { + component: 'bucket', + technology: 'ansible', + hosting: ['minio.server', '*', 'local.machine'], + // TODO: which weight? most likely 1 + weight: 1, + reason: 'Primary use case due to the specialization of Ansible.', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...GCPProviderCredentials(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/index.ts new file mode 100644 index 0000000000..c76a810960 --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/index.ts @@ -0,0 +1,4 @@ +import ansible from './ansible' +import terraform from './terraform' + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/terraform/index.ts new file mode 100644 index 0000000000..ca6a75cfee --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/terraform/index.ts @@ -0,0 +1,45 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + GCPProviderCredentials, + MetadataGenerated, + MetadataUnfurl, + TerraformStandardOperations, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this, see https://registry.terraform.io/providers/aminueza/minio/latest + +const generator: ImplementationGenerator = { + component: 'bucket', + technology: 'terraform', + hosting: ['minio.server', '*', 'local.machine'], + weight: 1, + reason: 'Terraform provides a declarative module.', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...GCPProviderCredentials(), + }, + + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + terraform: [], + provider: {}, + resource: {}, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/ansible/index.ts new file mode 100644 index 0000000000..f74ec3e987 --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/ansible/index.ts @@ -0,0 +1,59 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleOrchestratorOperation, + GCPProviderCredentials, + MetadataGenerated, + MetadataUnfurl, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this + +const generator: ImplementationGenerator = { + component: 'bucket', + technology: 'ansible', + hosting: ['minio.server', '*', 'remote.machine'], + // TODO: which weight? most likely 1 + weight: 1, + reason: 'Primary use case due to the specialization of Ansible.', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...GCPProviderCredentials(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/index.ts new file mode 100644 index 0000000000..c76a810960 --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/index.ts @@ -0,0 +1,4 @@ +import ansible from './ansible' +import terraform from './terraform' + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/terraform/index.ts new file mode 100644 index 0000000000..f5ee64fb68 --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/terraform/index.ts @@ -0,0 +1,49 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + GCPProviderCredentials, + MetadataGenerated, + MetadataUnfurl, + TerraformStandardOperations, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this, see https://registry.terraform.io/providers/aminueza/minio/latest + +const generator: ImplementationGenerator = { + component: 'bucket', + technology: 'terraform', + hosting: ['minio.server', '*', 'remote.machine'], + weight: 1, + reason: 'Terraform provides a declarative module.', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...GCPProviderCredentials(), + }, + + interfaces: { + ...TerraformStandardOperations({ + GOOGLE_APPLICATION_CREDENTIALS: { + eval: '.::gcp_service_account_file', + }, + }), + defaults: { + inputs: { + main: { + terraform: [], + provider: {}, + resource: {}, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/bucket/minio/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/index.ts new file mode 100644 index 0000000000..6c3cd92eb1 --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/minio/index.ts @@ -0,0 +1,4 @@ +import asterisk from './asterisk' +import kubernetesCluster from './kubernetes-cluster' + +export default [asterisk, kubernetesCluster] diff --git a/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/ansible/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/ansible/index.ts new file mode 100644 index 0000000000..5267ebc040 --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/ansible/index.ts @@ -0,0 +1,59 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleOrchestratorOperation, + GCPProviderCredentials, + MetadataGenerated, + MetadataUnfurl, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this + +const generator: ImplementationGenerator = { + component: 'bucket', + technology: 'ansible', + hosting: ['minio.server', 'kubernetes.cluster'], + // TODO: which weight? most likely 1 + weight: 1, + reason: 'Primary use case due to the specialization of Ansible.', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...GCPProviderCredentials(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/index.ts new file mode 100644 index 0000000000..c76a810960 --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/index.ts @@ -0,0 +1,4 @@ +import ansible from './ansible' +import terraform from './terraform' + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/terraform/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/terraform/index.ts new file mode 100644 index 0000000000..1cf64ed9fc --- /dev/null +++ b/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/terraform/index.ts @@ -0,0 +1,49 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + GCPProviderCredentials, + MetadataGenerated, + MetadataUnfurl, + TerraformStandardOperations, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this, see https://registry.terraform.io/providers/aminueza/minio/latest + +const generator: ImplementationGenerator = { + component: 'bucket', + technology: 'terraform', + hosting: ['minio.server', 'kubernetes.cluster'], + weight: 1, + reason: 'Terraform provides a declarative module.', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...GCPProviderCredentials(), + }, + + interfaces: { + ...TerraformStandardOperations({ + GOOGLE_APPLICATION_CREDENTIALS: { + eval: '.::gcp_service_account_file', + }, + }), + defaults: { + inputs: { + main: { + terraform: [], + provider: {}, + resource: {}, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/docker-engine/index.ts b/src/technologies/plugins/rules/generators/docker-engine/index.ts index 37846c4803..1fd9f3e86c 100644 --- a/src/technologies/plugins/rules/generators/docker-engine/index.ts +++ b/src/technologies/plugins/rules/generators/docker-engine/index.ts @@ -1,3 +1,4 @@ +import localMachine from './local-machine' import remoteMachine from './remote-machine' -export default [remoteMachine] +export default [localMachine, remoteMachine] diff --git a/src/technologies/plugins/rules/generators/docker-engine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/docker-engine/local-machine/ansible/index.ts new file mode 100644 index 0000000000..4cd57709f8 --- /dev/null +++ b/src/technologies/plugins/rules/generators/docker-engine/local-machine/ansible/index.ts @@ -0,0 +1,160 @@ +import * as files from '#files' +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleOrchestratorOperation, + AnsibleWaitForSSHTask, + MetadataGenerated, + MetadataUnfurl, +} from '#technologies/plugins/rules/utils' + +// TODO: maybe dont install but only check if installed? + +const generator: ImplementationGenerator = { + component: 'docker.engine', + technology: 'ansible', + hosting: ['local.machine'], + weight: 1, + reason: 'Primary use case due to the specialization of Ansible.', + 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: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + attributes: { + application_address: { + type: 'string', + default: '127.0.0.1', + }, + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + { + name: 'install docker', + '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: service, + }, + }, + { + 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', + }, + }, + { + name: 'add user to docker group', + 'ansible.builtin.user': { + name: '{{ SELF.os_ssh_user }}', + groups: 'docker', + append: 'yes', + }, + }, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + // 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'], + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/docker-engine/local-machine/index.ts b/src/technologies/plugins/rules/generators/docker-engine/local-machine/index.ts new file mode 100644 index 0000000000..c76a810960 --- /dev/null +++ b/src/technologies/plugins/rules/generators/docker-engine/local-machine/index.ts @@ -0,0 +1,4 @@ +import ansible from './ansible' +import terraform from './terraform' + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/docker-engine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/docker-engine/local-machine/terraform/index.ts new file mode 100644 index 0000000000..8ddf9fbe77 --- /dev/null +++ b/src/technologies/plugins/rules/generators/docker-engine/local-machine/terraform/index.ts @@ -0,0 +1,149 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {MetadataGenerated, MetadataUnfurl, TerraformStandardOperations} from '#technologies/plugins/rules/utils' +import * as utils from '#utils' + +// TODO: maybe dont install but only check if installed? +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', + technology: 'terraform', + hosting: ['local.machine'], + weight: 0, + reason: 'Ansible is more specialized. Also using provisioners is a "last resort".', + details: '"local-exec" provider', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + attributes: { + application_address: { + type: 'string', + default: '127.0.0.1', + }, + }, + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + terraform: [ + { + required_providers: [ + { + mysql: { + source: 'hashicorp/local', + version: '2.5.1', + }, + }, + ], + }, + ], + provider: { + local: [ + { + endpoint: '127.0.0.1:{{ HOST.management_port }}', + password: '{{ HOST.dbms_password }}', + username: 'root', + }, + ], + }, + resource: { + local_file: { + tmp_service: { + content: service, + filename: '/tmp/docker.service', + }, + }, + terraform_data: { + docker: [ + { + depends_on: 'local_file.tmp_service', + provisioner: { + 'local-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', + }, + ], + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/index.ts b/src/technologies/plugins/rules/generators/index.ts index 50b642f27e..c12e4ff477 100644 --- a/src/technologies/plugins/rules/generators/index.ts +++ b/src/technologies/plugins/rules/generators/index.ts @@ -1,18 +1,22 @@ +import bucket from './bucket' import dockerEngine from './docker-engine' import gcpService from './gcp-service' import ingress from './ingress' import mysqlDatabase from './mysql-database' import mysqlDBMS from './mysql-dbms' +import redisServer from './redis-server' import serviceApplication from './service-application' import softwareApplication from './software-application' import remoteMachine from './virtual-machine' export default [ + bucket, dockerEngine, gcpService, ingress, mysqlDatabase, mysqlDBMS, + redisServer, serviceApplication, softwareApplication, remoteMachine, 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 37846c4803..1fd9f3e86c 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,4 @@ +import localMachine from './local-machine' import remoteMachine from './remote-machine' -export default [remoteMachine] +export default [localMachine, remoteMachine] diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/ansible/index.ts new file mode 100644 index 0000000000..a092cd29b2 --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/ansible/index.ts @@ -0,0 +1,101 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils' + +const generator: ImplementationGenerator = { + component: 'mysql.database', + technology: 'ansible', + hosting: ['mysql.dbms', 'docker.engine', 'local.machine'], + weight: 1, + 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: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + name: 'get dbms container info', + 'community.docker.docker_container_info': { + name: '{{ HOST.dbms_name }}', + }, + register: 'dbms_container_info', + }, + { + name: 'create database', + 'community.mysql.mysql_db': { + name: '{{ SELF.database_name }}', + ...login, + }, + }, + { + name: 'create user (with privileges)', + 'community.mysql.mysql_user': { + ...user, + ...login, + }, + }, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + 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, + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/compose/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/compose/index.ts new file mode 100644 index 0000000000..55e7a8c968 --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/compose/index.ts @@ -0,0 +1,124 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation, MetadataGenerated, MetadataUnfurl} 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', 'local.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', + }, + }, + { + 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', + }, + }, + ] + + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + 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/local-machine/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/index.ts new file mode 100644 index 0000000000..644370664b --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/index.ts @@ -0,0 +1,5 @@ +import ansible from './ansible' +import compose from './compose' +import terraform from './terraform' + +export default [ansible, compose, terraform] diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/terraform/index.ts new file mode 100644 index 0000000000..a2896369be --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/terraform/index.ts @@ -0,0 +1,95 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + MetadataGenerated, + MetadataUnfurl, + OpenstackMachineCredentials, + OpenstackMachineHost, + TerraformStandardOperations, +} from '#technologies/plugins/rules/utils' + +// TODO: we assume that dbms is exposed + +const generator: ImplementationGenerator = { + component: 'mysql.database', + technology: 'terraform', + hosting: ['mysql.dbms', 'docker.engine', 'local.machine'], + + // TODO: what is about the weight? SSH workaround not used anymore + weight: 0.5, + reason: 'Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized.', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...OpenstackMachineCredentials(), + ...OpenstackMachineHost(), + }, + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + terraform: [ + { + required_providers: [ + { + mysql: { + source: 'petoju/mysql', + version: '3.0.48', + }, + }, + ], + }, + ], + provider: { + mysql: [ + { + endpoint: '127.0.0.1:{{ HOST.management_port }}', + password: '{{ HOST.dbms_password }}', + username: 'root', + }, + ], + }, + resource: { + mysql_database: { + database: [ + { + name: '{{ SELF.database_name }}', + }, + ], + }, + mysql_user: { + user: [ + { + host: '%', + plaintext_password: '{{ SELF.database_password }}', + user: '{{ SELF.database_user }}', + }, + ], + }, + mysql_grant: { + user: [ + { + database: '{{ SELF.database_name }}', + host: '%', + table: '*', + privileges: ['ALL'], + user: '${mysql_user.user.user}', + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator 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 37846c4803..1fd9f3e86c 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,4 @@ +import localMachine from './local-machine' import remoteMachine from './remote-machine' -export default [remoteMachine] +export default [localMachine, remoteMachine] diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/ansible/index.ts new file mode 100644 index 0000000000..1b7988fe2e --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/ansible/index.ts @@ -0,0 +1,90 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils' + +const generator: ImplementationGenerator = { + component: 'mysql.dbms', + technology: 'ansible', + artifact: 'dbms.image', + hosting: ['docker.engine', 'local.machine'], + weight: 0.5, + reason: 'Docker Compose is more specialized', + details: '"community.docker.docker_container" task', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + attributes: { + application_address: { + type: 'string', + default: '127.0.0.1', + }, + application_port: { + type: 'string', + default: 3306, + }, + management_address: { + type: 'string', + default: { + eval: '.::.requirements::[.name=host]::.target::management_address', + }, + }, + management_port: { + type: 'integer', + default: 3306, + }, + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + name: 'start container', + 'community.docker.docker_container': { + name: '{{ SELF.dbms_name }}', + image: 'mysql:{{ ".artifacts::dbms_image::file" | eval }}', + network_mode: 'host', + env: { + MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password | string }}', + }, + }, + }, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + name: 'delete container', + 'community.docker.docker_container': { + name: '{{ SELF.dbms_name }}', + state: 'absent', + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/compose/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/compose/index.ts new file mode 100644 index 0000000000..d1e86a2c8d --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/compose/index.ts @@ -0,0 +1,135 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleHostEndpointCapability, + AnsibleOrchestratorOperation, + MetadataGenerated, + MetadataUnfurl, +} from '#technologies/plugins/rules/utils' + +const generator: ImplementationGenerator = { + component: 'mysql.dbms', + technology: 'compose', + artifact: 'dbms.image', + hosting: ['docker.engine', 'local.machine'], + weight: 1, + reason: 'Docker is the underlying technology.', + 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(), + }, + attributes: { + application_address: { + type: 'string', + default: '127.0.0.1', + }, + application_port: { + type: 'integer', + default: 3306, + }, + management_address: { + type: 'string', + default: { + eval: '.::.requirements::[.name=host]::.target::management_address', + }, + }, + management_port: { + type: 'integer', + default: 3306, + }, + }, + capabilities: { + ...AnsibleHostEndpointCapability(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + AnsibleTouchComposeTask, + AnsibleCreateComposeTask, + { + name: 'apply compose', + 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', + args: { + executable: '/usr/bin/bash', + }, + }, + { + name: 'let it cook', + 'ansible.builtin.pause': { + seconds: 10, + }, + }, + ], + }, + }, + }, + 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', + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/index.ts new file mode 100644 index 0000000000..644370664b --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/index.ts @@ -0,0 +1,5 @@ +import ansible from './ansible' +import compose from './compose' +import terraform from './terraform' + +export default [ansible, compose, terraform] diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/terraform/index.ts new file mode 100644 index 0000000000..78fe46f70e --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/terraform/index.ts @@ -0,0 +1,105 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleHostEndpointCapability, + MetadataGenerated, + MetadataUnfurl, + OpenstackMachineCredentials, + OpenstackMachineHost, + TerraformStandardOperations, +} from '#technologies/plugins/rules/utils' + +const generator: ImplementationGenerator = { + component: 'mysql.dbms', + technology: 'terraform', + artifact: 'dbms.image', + hosting: ['docker.engine', 'local.machine'], + weight: 0.5, + reason: 'Docker Compose is more specialized.', + details: '"docker_container" and "docker_image" resources', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...OpenstackMachineCredentials(), + ...OpenstackMachineHost(), + }, + attributes: { + application_address: { + type: 'string', + default: '127.0.0.1', + }, + application_port: { + type: 'integer', + default: 3306, + }, + management_address: { + type: 'string', + default: { + eval: '.::.requirements::[.name=host]::.target::management_address', + }, + }, + management_port: { + type: 'integer', + default: 3306, + }, + }, + capabilities: { + ...AnsibleHostEndpointCapability(), + }, + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + terraform: [ + { + required_providers: [ + { + docker: { + source: 'kreuzwerker/docker', + version: '3.0.2', + }, + }, + ], + }, + ], + provider: { + docker: [ + { + host: 'unix:///var/run/docker.sock', + }, + ], + }, + resource: { + docker_container: { + application: [ + { + name: '{{ SELF.dbms_name }}', + image: '${docker_image.image.image_id}', + network_mode: 'host', + env: ['MYSQL_ROOT_PASSWORD={{ SELF.dbms_password }}'], + }, + ], + }, + docker_image: { + image: [ + { + name: 'mysql:{{ ".artifacts::dbms_image::file" | eval }}', + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/index.ts new file mode 100644 index 0000000000..1fd9f3e86c --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/index.ts @@ -0,0 +1,4 @@ +import localMachine from './local-machine' +import remoteMachine from './remote-machine' + +export default [localMachine, remoteMachine] diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/ansible/index.ts new file mode 100644 index 0000000000..e7f11ab0a0 --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/ansible/index.ts @@ -0,0 +1,81 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleOrchestratorOperation, + MetadataGenerated, + MetadataUnfurl, + mapProperties, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this + +const generator: ImplementationGenerator = { + component: 'redis.server', + technology: 'ansible', + artifact: 'cache.image', + hosting: ['docker.engine', 'local.machine'], + weight: 0.5, + reason: 'Docker Compose is more specialized.', + details: '"community.docker.docker_container" task', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + attributes: { + application_address: { + type: 'string', + default: '127.0.0.1', + }, + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + name: 'start container', + 'community.docker.docker_container': { + name: '{{ SELF.application_name }}', + image: '{{ ".artifacts::docker_image::file" | eval }}', + network_mode: 'host', + env: mapProperties(type, {format: 'map'}), + }, + }, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + name: 'stop container', + 'community.docker.docker_container': { + name: '{{ SELF.application_name }}', + state: 'absent', + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/compose/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/compose/index.ts new file mode 100644 index 0000000000..d2c956121d --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/compose/index.ts @@ -0,0 +1,112 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleOrchestratorOperation, + MetadataGenerated, + MetadataUnfurl, + mapProperties, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this + +const generator: ImplementationGenerator = { + component: 'redis.server', + technology: 'compose', + artifact: 'cache.image', + hosting: ['docker.engine', 'local.machine'], + weight: 1, + reason: 'Docker is the underlying technology.', + 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(), + }, + attributes: { + application_address: { + type: 'string', + default: '127.0.0.1', + }, + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + AnsibleTouchComposeTask, + AnsibleCreateComposeTask, + { + name: 'apply compose', + 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', + args: { + executable: '/usr/bin/bash', + }, + }, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + AnsibleTouchComposeTask, + AnsibleCreateComposeTask, + { + name: 'apply compose', + 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', + args: { + executable: '/usr/bin/bash', + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/index.ts new file mode 100644 index 0000000000..644370664b --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/index.ts @@ -0,0 +1,5 @@ +import ansible from './ansible' +import compose from './compose' +import terraform from './terraform' + +export default [ansible, compose, terraform] diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/terraform/index.ts new file mode 100644 index 0000000000..61488ee748 --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/terraform/index.ts @@ -0,0 +1,84 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + MetadataGenerated, + MetadataUnfurl, + TerraformStandardOperations, + mapProperties, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this + +const generator: ImplementationGenerator = { + component: 'redis.server', + technology: 'terraform', + artifact: 'cache.image', + hosting: ['docker.engine', 'local.machine'], + weight: 0.5, + reason: 'Docker Compose is more specialized.', + details: '"docker_container" and "docker_image" resources', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + attributes: { + application_address: { + type: 'string', + default: '127.0.0.1', + }, + }, + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + terraform: [ + { + required_providers: [ + { + docker: { + source: 'kreuzwerker/docker', + version: '3.0.2', + }, + }, + ], + }, + ], + provider: { + docker: [ + { + host: 'unix:///var/run/docker.sock', + }, + ], + }, + resource: { + docker_container: { + application: [ + { + env: mapProperties(type, {format: 'env', quote: false}), + image: '${docker_image.image.image_id}', + name: '{{ SELF.application_name }}', + network_mode: 'host', + }, + ], + }, + docker_image: { + image: [ + { + name: '{{ ".artifacts::docker_image::file" | eval }}', + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/ansible/index.ts new file mode 100644 index 0000000000..e04abd09cf --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/ansible/index.ts @@ -0,0 +1,93 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleHostOperation, + AnsibleHostOperationPlaybookArgs, + AnsibleWaitForSSHTask, + MetadataGenerated, + MetadataUnfurl, + OpenstackMachineCredentials, + mapProperties, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this + +const generator: ImplementationGenerator = { + component: 'redis.server', + technology: 'ansible', + artifact: 'cache.image', + hosting: ['docker.engine', 'remote.machine'], + weight: 0.5, + reason: 'Docker Compose is more specialized.', + details: '"community.docker.docker_container" task', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: {...OpenstackMachineCredentials()}, + attributes: { + application_address: { + type: 'string', + default: '127.0.0.1', + }, + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + { + name: 'start container', + 'community.docker.docker_container': { + name: '{{ SELF.application_name }}', + image: '{{ ".artifacts::docker_image::file" | eval }}', + network_mode: 'host', + env: mapProperties(type, {format: 'map'}), + }, + }, + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, + delete: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + { + name: 'stop container', + 'community.docker.docker_container': { + name: '{{ SELF.application_name }}', + state: 'absent', + }, + }, + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/compose/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/compose/index.ts new file mode 100644 index 0000000000..139df5de44 --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/compose/index.ts @@ -0,0 +1,123 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleDockerHostEnvironment, + AnsibleOrchestratorOperation, + MetadataGenerated, + MetadataUnfurl, + OpenstackMachineHost, + mapProperties, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this + +const generator: ImplementationGenerator = { + component: 'redis.server', + technology: 'compose', + artifact: 'cache.image', + hosting: ['docker.engine', 'remote.machine'], + weight: 1, + reason: 'Docker is the underlying technology.', + 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: { + ...OpenstackMachineHost(), + }, + attributes: { + application_address: { + type: 'string', + default: '127.0.0.1', + }, + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + AnsibleTouchComposeTask, + AnsibleCreateComposeTask, + { + name: 'apply compose', + 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', + args: { + executable: '/usr/bin/bash', + }, + environment: { + ...AnsibleDockerHostEnvironment(), + }, + }, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + AnsibleTouchComposeTask, + AnsibleCreateComposeTask, + { + name: 'apply compose', + 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', + args: { + executable: '/usr/bin/bash', + }, + environment: { + ...AnsibleDockerHostEnvironment(), + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/index.ts new file mode 100644 index 0000000000..644370664b --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/index.ts @@ -0,0 +1,5 @@ +import ansible from './ansible' +import compose from './compose' +import terraform from './terraform' + +export default [ansible, compose, terraform] diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/terraform/index.ts new file mode 100644 index 0000000000..9f7520b8e3 --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/terraform/index.ts @@ -0,0 +1,102 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + MetadataGenerated, + MetadataUnfurl, + OpenstackMachineCredentials, + OpenstackMachineHost, + TerraformStandardOperations, + mapProperties, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this + +const generator: ImplementationGenerator = { + component: 'redis.server', + technology: 'terraform', + artifact: 'cache.image', + hosting: ['docker.engine', 'remote.machine'], + weight: 0.5, + reason: 'Docker Compose is more specialized.', + details: '"docker_container" and "docker_image" resources', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...OpenstackMachineCredentials(), + ...OpenstackMachineHost(), + }, + attributes: { + application_address: { + type: 'string', + default: '127.0.0.1', + }, + }, + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + terraform: [ + { + required_providers: [ + { + docker: { + source: 'kreuzwerker/docker', + version: '3.0.2', + }, + }, + ], + }, + ], + provider: { + docker: [ + { + host: 'ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22', + ssh_opts: [ + '-i', + '{{ SELF.os_ssh_key_file }}', + '-o', + 'IdentitiesOnly=yes', + '-o', + 'BatchMode=yes', + '-o', + 'UserKnownHostsFile=/dev/null', + '-o', + 'StrictHostKeyChecking=no', + ], + }, + ], + }, + resource: { + docker_container: { + application: [ + { + env: mapProperties(type, {format: 'env', quote: false}), + image: '${docker_image.image.image_id}', + name: '{{ SELF.application_name }}', + network_mode: 'host', + }, + ], + }, + docker_image: { + image: [ + { + name: '{{ ".artifacts::docker_image::file" | eval }}', + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/ansible/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/ansible/index.ts new file mode 100644 index 0000000000..d2cbb70454 --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/ansible/index.ts @@ -0,0 +1,71 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleOrchestratorOperation, + GCPProviderCredentials, + MetadataGenerated, + MetadataUnfurl, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this, see https://docs.ansible.com/ansible/latest/collections/google/cloud/gcp_redis_instance_module.html + +const generator: ImplementationGenerator = { + component: 'bucket', + technology: 'ansible', + artifact: 'cache.image', + hosting: ['gcp.memorystore'], + weight: 0.5, + reason: 'Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this.', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...GCPProviderCredentials(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + environment: { + GCP_SERVICE_ACCOUNT_FILE: { + eval: '.::gcp_service_account_file', + }, + GCP_AUTH_KIND: 'serviceaccount', + }, + }, + inputs: { + playbook: { + q: [], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + environment: { + GCP_SERVICE_ACCOUNT_FILE: { + eval: '.::gcp_service_account_file', + }, + GCP_AUTH_KIND: 'serviceaccount', + }, + }, + inputs: { + playbook: { + q: [], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/index.ts new file mode 100644 index 0000000000..c76a810960 --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/index.ts @@ -0,0 +1,4 @@ +import ansible from './ansible' +import terraform from './terraform' + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/terraform/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/terraform/index.ts new file mode 100644 index 0000000000..8f2403ad52 --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/terraform/index.ts @@ -0,0 +1,73 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + GCPProviderCredentials, + MetadataGenerated, + MetadataUnfurl, + TerraformStandardOperations, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this, see https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/redis_instance + +const generator: ImplementationGenerator = { + component: 'redis.server', + technology: 'terraform', + artifact: 'cache.image', + hosting: ['gcp.memorystore'], + weight: 1, + reason: 'Terraform provides a declarative module.', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...GCPProviderCredentials(), + }, + + interfaces: { + ...TerraformStandardOperations({ + GOOGLE_APPLICATION_CREDENTIALS: { + eval: '.::gcp_service_account_file', + }, + }), + defaults: { + inputs: { + main: { + terraform: [ + { + required_providers: [ + { + google: { + source: 'hashicorp/google', + version: '5.39.1', + }, + mysql: { + source: 'petoju/mysql', + version: '3.0.48', + }, + }, + ], + }, + ], + provider: { + google: [ + { + credentials: '{{ SELF.gcp_service_account_file }}', + project: '{{ SELF.gcp_project }}', + region: '{{ SELF.gcp_region }}', + }, + ], + }, + resource: {}, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/index.ts new file mode 100644 index 0000000000..5f5aa9ba05 --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/index.ts @@ -0,0 +1,5 @@ +import dockerEngine from './docker-engine' +import gcpMemoryStore from './gcp-memorystore' +import kubernetesCluster from './kubernetes-cluster' + +export default [gcpMemoryStore, dockerEngine, kubernetesCluster] diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts new file mode 100644 index 0000000000..66929984ad --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts @@ -0,0 +1,58 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleOrchestratorOperation, + GCPProviderCredentials, + MetadataGenerated, + MetadataUnfurl, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this + +const generator: ImplementationGenerator = { + component: 'redis.server', + technology: 'ansible', + hosting: ['kubernetes.cluster'], + weight: 1, + reason: 'Primary use case due to the specialization of Ansible.', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...GCPProviderCredentials(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/index.ts new file mode 100644 index 0000000000..62d1a644b4 --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/index.ts @@ -0,0 +1,6 @@ +import ansible from './ansible' +import terraform from './terraform' + +// TODO: kubernetes + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts new file mode 100644 index 0000000000..fd8943665e --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts @@ -0,0 +1,49 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + GCPProviderCredentials, + MetadataGenerated, + MetadataUnfurl, + TerraformStandardOperations, +} from '#technologies/plugins/rules/utils' + +// TODO: next: implement this, see https://registry.terraform.io/providers/aminueza/minio/latest + +const generator: ImplementationGenerator = { + component: 'redis.server', + technology: 'terraform', + hosting: ['kubernetes.cluster'], + weight: 1, + reason: 'Terraform provides a declarative module.', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...GCPProviderCredentials(), + }, + + interfaces: { + ...TerraformStandardOperations({ + GOOGLE_APPLICATION_CREDENTIALS: { + eval: '.::gcp_service_account_file', + }, + }), + defaults: { + inputs: { + main: { + terraform: [], + provider: {}, + resource: {}, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/redis-server/index.ts b/src/technologies/plugins/rules/generators/redis-server/index.ts new file mode 100644 index 0000000000..8062d15e8b --- /dev/null +++ b/src/technologies/plugins/rules/generators/redis-server/index.ts @@ -0,0 +1,3 @@ +import cacheImage from './cache-image' + +export default [cacheImage] diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/index.ts index 37846c4803..1fd9f3e86c 100644 --- a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/index.ts @@ -1,3 +1,4 @@ +import localMachine from './local-machine' import remoteMachine from './remote-machine' -export default [remoteMachine] +export default [localMachine, remoteMachine] diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/ansible/index.ts new file mode 100644 index 0000000000..994fb21b7c --- /dev/null +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/ansible/index.ts @@ -0,0 +1,79 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleOrchestratorOperation, + MetadataGenerated, + MetadataUnfurl, + mapProperties, +} from '#technologies/plugins/rules/utils' + +const generator: ImplementationGenerator = { + component: 'service.application', + technology: 'ansible', + artifact: 'docker.image', + hosting: ['docker.engine', 'local.machine'], + weight: 0.5, + reason: 'Docker Compose is more specialized.', + details: '"community.docker.docker_container" task', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + attributes: { + application_address: { + type: 'string', + default: '127.0.0.1', + }, + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + name: 'start container', + 'community.docker.docker_container': { + name: '{{ SELF.application_name }}', + image: '{{ ".artifacts::docker_image::file" | eval }}', + network_mode: 'host', + env: mapProperties(type, {format: 'map'}), + }, + }, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + name: 'stop container', + 'community.docker.docker_container': { + name: '{{ SELF.application_name }}', + state: 'absent', + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/compose/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/compose/index.ts new file mode 100644 index 0000000000..e87454877e --- /dev/null +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/compose/index.ts @@ -0,0 +1,110 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleOrchestratorOperation, + MetadataGenerated, + MetadataUnfurl, + mapProperties, +} from '#technologies/plugins/rules/utils' + +const generator: ImplementationGenerator = { + component: 'service.application', + technology: 'compose', + artifact: 'docker.image', + hosting: ['docker.engine', 'local.machine'], + weight: 1, + reason: 'Docker is the underlying technology.', + 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(), + }, + attributes: { + application_address: { + type: 'string', + default: '127.0.0.1', + }, + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + AnsibleTouchComposeTask, + AnsibleCreateComposeTask, + { + name: 'apply compose', + 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', + args: { + executable: '/usr/bin/bash', + }, + }, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + AnsibleTouchComposeTask, + AnsibleCreateComposeTask, + { + name: 'apply compose', + 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', + args: { + executable: '/usr/bin/bash', + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/index.ts new file mode 100644 index 0000000000..644370664b --- /dev/null +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/index.ts @@ -0,0 +1,5 @@ +import ansible from './ansible' +import compose from './compose' +import terraform from './terraform' + +export default [ansible, compose, terraform] diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/terraform/index.ts new file mode 100644 index 0000000000..ffe868adab --- /dev/null +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/terraform/index.ts @@ -0,0 +1,82 @@ +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + MetadataGenerated, + MetadataUnfurl, + TerraformStandardOperations, + mapProperties, +} from '#technologies/plugins/rules/utils' + +const generator: ImplementationGenerator = { + component: 'service.application', + technology: 'terraform', + artifact: 'docker.image', + hosting: ['docker.engine', 'local.machine'], + weight: 0.5, + reason: 'Docker Compose is more specialized.', + details: '"docker_container" and "docker_image" resources', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + attributes: { + application_address: { + type: 'string', + default: '127.0.0.1', + }, + }, + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + terraform: [ + { + required_providers: [ + { + docker: { + source: 'kreuzwerker/docker', + version: '3.0.2', + }, + }, + ], + }, + ], + provider: { + docker: [ + { + host: 'unix:///var/run/docker.sock', + }, + ], + }, + resource: { + docker_container: { + application: [ + { + env: mapProperties(type, {format: 'env', quote: false}), + image: '${docker_image.image.image_id}', + name: '{{ SELF.application_name }}', + network_mode: 'host', + }, + ], + }, + docker_image: { + image: [ + { + name: '{{ ".artifacts::docker_image::file" | eval }}', + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator From d2889a49d01b1561b14b0fb35beaf574bb3ed32a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Fri, 6 Sep 2024 17:38:43 +0200 Subject: [PATCH 03/18] fix --- .../lib/rules.yaml | 2 ++ .../lib/tosca-vintner-profile-extended.yaml | 4 ++-- .../scripts/configuration.env | 2 +- .../scripts/quality.sh | 7 ++++++- .../variable-service-template.yaml | 6 +++--- .../cache-image/kubernetes-cluster/ansible/index.ts | 1 + .../cache-image/kubernetes-cluster/terraform/index.ts | 1 + 7 files changed, 16 insertions(+), 7 deletions(-) diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml index 2d6347a352..971f770e97 100644 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml @@ -151,6 +151,7 @@ ansible: reason: Docker Compose is more specialized. details: '"community.docker.docker_container" task' - component: redis.server + artifact: cache.image hosting: - kubernetes.cluster weight: 1 @@ -386,6 +387,7 @@ terraform: reason: Docker Compose is more specialized. details: '"docker_container" and "docker_image" resources' - component: redis.server + artifact: cache.image hosting: - kubernetes.cluster weight: 1 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml index cba7faf8a5..afb9977532 100644 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml @@ -14545,7 +14545,7 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - redis.server~redis.server::ansible@kubernetes.cluster: + redis.server~redis.server#cache.image::ansible@kubernetes.cluster: derived_from: redis.server metadata: vintner_generated: 'true' @@ -15411,7 +15411,7 @@ node_types: docker_image: image: - name: '{{ ".artifacts::docker_image::file" | eval }}' - redis.server~redis.server::terraform@kubernetes.cluster: + redis.server~redis.server#cache.image::terraform@kubernetes.cluster: derived_from: redis.server metadata: vintner_generated: 'true' diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.env b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.env index 0764bfb3f1..047812aaf3 100644 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.env +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.env @@ -2,4 +2,4 @@ TEMPLATE_NAME="technology-gcp" #VINTNER="node ../../../build/cli/index.js" VINTNER="../../../task vintner" ORCHESTRATOR="unfurl" -VARIANT="os-medium" +VARIANT="local" diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh index a1971f736c..60f7018a34 100755 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh @@ -5,4 +5,9 @@ set -e source configuration.sh # Quality -$VINTNER template quality --template ${TEMPLATE_DIR}/variable-service-template.yaml --experimental +for dir in ../tests/*/; +#for dir in "../tests/gcp"; +do + dir=$(basename $dir) + echo "${dir}: $($VINTNER template quality --template ${TEMPLATE_DIR}/variable-service-template.yaml --experimental --inputs ${TEMPLATE_DIR}/tests/${dir}/inputs.yaml)" +done diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml index 33520b274e..c6454757be 100644 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml @@ -111,9 +111,9 @@ topology_template: # TODO: remove these options: - technology_constraint: false - required_artifact_constraint: false - required_incoming_relation_constraint: false + #technology_constraint: false + #required_artifact_constraint: false + #expected_artifact_check: true inputs: env: diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts index 66929984ad..d554e42727 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts @@ -11,6 +11,7 @@ import { const generator: ImplementationGenerator = { component: 'redis.server', technology: 'ansible', + artifact: 'cache.image', hosting: ['kubernetes.cluster'], weight: 1, reason: 'Primary use case due to the specialization of Ansible.', diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts index fd8943665e..26a6fd2286 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts @@ -11,6 +11,7 @@ import { const generator: ImplementationGenerator = { component: 'redis.server', technology: 'terraform', + artifact: 'cache.image', hosting: ['kubernetes.cluster'], weight: 1, reason: 'Terraform provides a declarative module.', From 04ed58fc3dce05bebe67521baa458b0a6d24ba25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Fri, 6 Sep 2024 17:43:41 +0200 Subject: [PATCH 04/18] minor --- .../variable-service-template.yaml | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml index c6454757be..17ec92db89 100644 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml +++ b/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml @@ -188,6 +188,13 @@ topology_template: type: docker.image file: retailer.frontend.dashboard:vX.Y.Z + retailer_ingress_dashboard: + type: ingress + requirements: + - application: retailer_frontend_dashboard + - host: virtual_machine + - host: kubernetes_cluster + ################################################### # # Retailer Terminal @@ -219,6 +226,13 @@ topology_template: type: docker.image file: retailer.frontend.dashboard:vX.Y.Z + retailer_ingress_terminal: + type: ingress + requirements: + - application: retailer_frontend_terminal + - host: virtual_machine + - host: kubernetes_cluster + ################################################### # # Retailer Gateway @@ -291,8 +305,7 @@ topology_template: type: docker.image file: retailer.service.gateway:vX.Y.Z - # TODO: frontends brauchen auch ingressessesesss - retailer_gateway_ingress: + retailer_ingress_gateway: type: ingress requirements: - application: retailer_service_gateway @@ -455,7 +468,6 @@ topology_template: requirements: - host: retailer_dbms - # TODO: is missing implementation if minio is hosted on k8s retailer_bucket_stores: type: bucket properties: @@ -725,7 +737,6 @@ topology_template: - host: gcp_memorystore - host: node: kubernetes_cluster - # TODO: this might not be required conditions: {logic_expression: is_customer} artifacts: - cache_image: @@ -740,7 +751,6 @@ topology_template: retailer_minio: type: minio.server - # TODO: remove this? but complains about ambiguous in when hyperscaler conditions: {not: {logic_expression: is_hyperscaler}} properties: - application_name: retailer-minio-server From b66e80a2f5f6b29092914fd68745e81c4184643e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Sat, 7 Sep 2024 19:42:35 +0200 Subject: [PATCH 05/18] fixes --- docs/docs/variability4tosca/rules/index.md | 1263 ++++++++++++----- .../rules/technology-rules.yaml | 1198 ++++++++-------- .../lib/rules.yaml | 568 -------- tasks/docs/generate/rules/task.ts | 4 +- tasks/docs/generate/rules/template.ejs | 17 +- 5 files changed, 1556 insertions(+), 1494 deletions(-) delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml diff --git a/docs/docs/variability4tosca/rules/index.md b/docs/docs/variability4tosca/rules/index.md index 399db5637e..bf5c45b041 100644 --- a/docs/docs/variability4tosca/rules/index.md +++ b/docs/docs/variability4tosca/rules/index.md @@ -60,6 +60,89 @@ We use the following derivation rules to assess deployment qualities. +## Component "bucket" + +The following scenarios deploy a node template of node type [bucket](/normative#bucket){target=_blank} with various hosting stacks, artifacts, deployment technologies, and qualities. + + +### Scenario #1 + +In this scenario, the node template "component" of node type [bucket](/normative#bucket){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [gcp.cloudstorage](/normative#gcpcloudstorage){target=_blank}. + +
component(bucket)host 1(gcp.cloudstorage)host
+ + +!!! info "Ansible (Quality: 0.5)" + Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. + + + +### Scenario #2 + +In this scenario, the node template "component" of node type [bucket](/normative#bucket){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [minio.server](/normative#minioserver){target=_blank}, which is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 3" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(bucket)host 1(minio.server)...host 3(local.machine)hosthosthost
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. + + + +### Scenario #3 + +In this scenario, the node template "component" of node type [bucket](/normative#bucket){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [minio.server](/normative#minioserver){target=_blank}, which is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 3" of node type [remote.machine](/normative#remotemachine){target=_blank}. + +
component(bucket)host 1(minio.server)...host 3(remote.machine)hosthosthost
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. + + + +### Scenario #4 + +In this scenario, the node template "component" of node type [bucket](/normative#bucket){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [minio.server](/normative#minioserver){target=_blank}, which is hosted on the node template "host 2" of node type [kubernetes.cluster](/normative#kubernetescluster){target=_blank}. + +
component(bucket)host 1(minio.server)host 2(kubernetes.cluster)hosthost
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. + + + +### Scenario #5 + +In this scenario, the node template "component" of node type [bucket](/normative#bucket){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [gcp.memorystore](/normative#gcpmemorystore){target=_blank}. + +
component(bucket)artifact(cache.image)host 1(gcp.memorystore)host
+ + +!!! info "Ansible (Quality: 0.5)" + Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. + + + ## Component "docker.engine" The following scenarios deploy a node template of node type [docker.engine](/normative#dockerengine){target=_blank} with various hosting stacks, artifacts, deployment technologies, and qualities. @@ -67,6 +150,22 @@ The following scenarios deploy a node template of node type [docker.engine](/nor ### Scenario #1 +In this scenario, the node template "component" of node type [docker.engine](/normative#dockerengine){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(docker.engine)host 1(local.machine)host
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! failure "Terraform (Quality: 0)" + Ansible is more specialized. Also using provisioners is a "last resort". + + + +### Scenario #2 + In this scenario, the node template "component" of node type [docker.engine](/normative#dockerengine){target=_blank} is deployed. The node template is hosted on the node template "host 1" of node type [remote.machine](/normative#remotemachine){target=_blank}. @@ -118,12 +217,12 @@ The node template is hosted on the node template "host 1" of node type [kubernet !!! info "Ansible (Quality: 0.5)" Kubernetes is more specialized. -!!! info "Terraform (Quality: 0.5)" - Kubernetes is more specialized. - !!! success "Kubernetes (Quality: 1)" Kubernetes is the underlying technology. +!!! info "Terraform (Quality: 0.5)" + Kubernetes is more specialized. + ### Scenario #2 @@ -150,23 +249,42 @@ The following scenarios deploy a node template of node type [mysql.database](/no ### Scenario #1 In this scenario, the node template "component" of node type [mysql.database](/normative#mysqldatabase){target=_blank} is deployed. -The node template is hosted on the node template "host 1" of node type [mysql.dbms](/normative#mysqldbms){target=_blank}, which is hosted on the node template "host 2" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 3" of node type [remote.machine](/normative#remotemachine){target=_blank}. +The node template is hosted on the node template "host 1" of node type [mysql.dbms](/normative#mysqldbms){target=_blank}, which is hosted on the node template "host 2" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 3" of node type [local.machine](/normative#localmachine){target=_blank}. -
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(remote.machine)hosthosthost
+
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(local.machine)hosthosthost
!!! success "Ansible (Quality: 1)" Primary use case due to the specialization of Ansible. +!!! failure "Docker Compose (Quality: 0)" + One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. + !!! info "Terraform (Quality: 0.5)" Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. + + +### Scenario #2 + +In this scenario, the node template "component" of node type [mysql.database](/normative#mysqldatabase){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [mysql.dbms](/normative#mysqldbms){target=_blank}, which is hosted on the node template "host 2" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 3" of node type [remote.machine](/normative#remotemachine){target=_blank}. + +
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(remote.machine)hosthosthost
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + !!! failure "Docker Compose (Quality: 0)" One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. +!!! info "Terraform (Quality: 0.5)" + Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. + -### Scenario #2 +### Scenario #3 In this scenario, the node template "component" of node type [mysql.database](/normative#mysqldatabase){target=_blank} is deployed. The node template is hosted on the node template "host 1" of node type [mysql.dbms](/normative#mysqldbms){target=_blank}, which is hosted on the node template "host 2" of node type [gcp.cloudsql](/normative#gcpcloudsql){target=_blank}. @@ -182,7 +300,7 @@ The node template is hosted on the node template "host 1" of node type [mysql.db -### Scenario #3 +### Scenario #4 In this scenario, the node template "component" of node type [mysql.database](/normative#mysqldatabase){target=_blank} is deployed. The node template is hosted on the node template "host 1" of node type [mysql.dbms](/normative#mysqldbms){target=_blank}, which is hosted on the node template "host 2" of node type [kubernetes.cluster](/normative#kubernetescluster){target=_blank}. @@ -193,15 +311,15 @@ The node template is hosted on the node template "host 1" of node type [mysql.db !!! success "Ansible (Quality: 1)" Primary use case due to the specialization of Ansible. -!!! failure "Terraform (Quality: 0)" - Ansible is more specialized. - !!! failure "Kubernetes (Quality: 0)" Kubernetes Job with imperative parts, while declarative other technologies provide declarative modules. +!!! failure "Terraform (Quality: 0)" + Ansible is more specialized. -### Scenario #4 + +### Scenario #5 In this scenario, the node template "component" of node type [mysql.database](/normative#mysqldatabase){target=_blank} is deployed. The node template is hosted on the node template "host 1" of node type [mysql.dbms](/normative#mysqldbms){target=_blank}, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. @@ -226,23 +344,43 @@ The following scenarios deploy a node template of node type [mysql.dbms](/normat In this scenario, the node template "component" of node type [mysql.dbms](/normative#mysqldbms){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [dbms.image](/normative#dbmsimage){target=_blank}. -The node template is hosted on the node template "host 1" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. +The node template is hosted on the node template "host 1" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. -
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(remote.machine)hosthost
+
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(local.machine)hosthost
!!! info "Ansible (Quality: 0.5)" Docker Compose is more specialized +!!! success "Docker Compose (Quality: 1)" + Docker is the underlying technology. + !!! info "Terraform (Quality: 0.5)" Docker Compose is more specialized. + + +### Scenario #2 + +In this scenario, the node template "component" of node type [mysql.dbms](/normative#mysqldbms){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [dbms.image](/normative#dbmsimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. + +
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(remote.machine)hosthost
+ + +!!! info "Ansible (Quality: 0.5)" + Docker Compose is more specialized + !!! success "Docker Compose (Quality: 1)" Docker is the underlying technology. +!!! info "Terraform (Quality: 0.5)" + Docker Compose is more specialized. -### Scenario #2 + +### Scenario #3 In this scenario, the node template "component" of node type [mysql.dbms](/normative#mysqldbms){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [dbms.image](/normative#dbmsimage){target=_blank}. @@ -259,7 +397,7 @@ The node template is hosted on the node template "host 1" of node type [gcp.clou -### Scenario #3 +### Scenario #4 In this scenario, the node template "component" of node type [mysql.dbms](/normative#mysqldbms){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [dbms.image](/normative#dbmsimage){target=_blank}. @@ -271,15 +409,15 @@ The node template is hosted on the node template "host 1" of node type [kubernet !!! info "Ansible (Quality: 0.5)" Kubernetes is more specialized. -!!! info "Terraform (Quality: 0.5)" - Kubernetes is more specialized. - !!! success "Kubernetes (Quality: 1)" Kubernetes is the underlying technology. +!!! info "Terraform (Quality: 0.5)" + Kubernetes is more specialized. + -### Scenario #4 +### Scenario #5 In this scenario, the node template "component" of node type [mysql.dbms](/normative#mysqldbms){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [dbms.image](/normative#dbmsimage){target=_blank}. @@ -296,6 +434,82 @@ The node template is hosted on the node template "host 1" of node type [remote.m +## Component "redis.server" + +The following scenarios deploy a node template of node type [redis.server](/normative#redisserver){target=_blank} with various hosting stacks, artifacts, deployment technologies, and qualities. + + +### Scenario #1 + +In this scenario, the node template "component" of node type [redis.server](/normative#redisserver){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [gcp.memorystore](/normative#gcpmemorystore){target=_blank}. + +
component(redis.server)artifact(cache.image)host 1(gcp.memorystore)host
+ + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. + + + +### Scenario #2 + +In this scenario, the node template "component" of node type [redis.server](/normative#redisserver){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(local.machine)hosthost
+ + +!!! info "Ansible (Quality: 0.5)" + Docker Compose is more specialized. + +!!! success "Docker Compose (Quality: 1)" + Docker is the underlying technology. + +!!! info "Terraform (Quality: 0.5)" + Docker Compose is more specialized. + + + +### Scenario #3 + +In this scenario, the node template "component" of node type [redis.server](/normative#redisserver){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. + +
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(remote.machine)hosthost
+ + +!!! info "Ansible (Quality: 0.5)" + Docker Compose is more specialized. + +!!! success "Docker Compose (Quality: 1)" + Docker is the underlying technology. + +!!! info "Terraform (Quality: 0.5)" + Docker Compose is more specialized. + + + +### Scenario #4 + +In this scenario, the node template "component" of node type [redis.server](/normative#redisserver){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [kubernetes.cluster](/normative#kubernetescluster){target=_blank}. + +
component(redis.server)artifact(cache.image)host 1(kubernetes.cluster)host
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. + + + ## Component "service.application" The following scenarios deploy a node template of node type [service.application](/normative#serviceapplication){target=_blank} with various hosting stacks, artifacts, deployment technologies, and qualities. @@ -305,23 +519,43 @@ The following scenarios deploy a node template of node type [service.application In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [docker.image](/normative#dockerimage){target=_blank}. -The node template is hosted on the node template "host 1" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. +The node template is hosted on the node template "host 1" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. -
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
+
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(local.machine)hosthost
!!! info "Ansible (Quality: 0.5)" Docker Compose is more specialized. +!!! success "Docker Compose (Quality: 1)" + Docker is the underlying technology. + !!! info "Terraform (Quality: 0.5)" Docker Compose is more specialized. + + +### Scenario #2 + +In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [docker.image](/normative#dockerimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. + +
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
+ + +!!! info "Ansible (Quality: 0.5)" + Docker Compose is more specialized. + !!! success "Docker Compose (Quality: 1)" Docker is the underlying technology. +!!! info "Terraform (Quality: 0.5)" + Docker Compose is more specialized. + -### Scenario #2 +### Scenario #3 In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [docker.image](/normative#dockerimage){target=_blank}. @@ -338,7 +572,7 @@ The node template is hosted on the node template "host 1" of node type [gcp.clou -### Scenario #3 +### Scenario #4 In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [docker.image](/normative#dockerimage){target=_blank}. @@ -350,15 +584,15 @@ The node template is hosted on the node template "host 1" of node type [kubernet !!! info "Ansible (Quality: 0.5)" Kubernetes is more specialized. -!!! info "Terraform (Quality: 0.5)" - Kubernetes is more specialized. - !!! success "Kubernetes (Quality: 1)" Kubernetes is the underlying technology. +!!! info "Terraform (Quality: 0.5)" + Kubernetes is more specialized. -### Scenario #4 + +### Scenario #5 In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [tar.archive](/normative#tararchive){target=_blank}. @@ -375,7 +609,7 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w -### Scenario #5 +### Scenario #6 In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [zip.archive](/normative#ziparchive){target=_blank}. @@ -392,7 +626,7 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w -### Scenario #6 +### Scenario #7 In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [zip.archive](/normative#ziparchive){target=_blank}. @@ -431,14 +665,11 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w ### Scenario #2 In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. -This node template is implemented by its deployment artifact "artifact" of artifact type [tar.archive](/normative#tararchive){target=_blank}. +This node template is implemented by its deployment artifact "artifact" of artifact type [apt.archive](/normative#aptarchive){target=_blank}. The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. -
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
- +
component(software.application)artifact(apt.archive)...host 2(remote.machine)hosthost
-!!! info "Ansible (Quality: 0.5)" - While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application". !!! failure "Terraform (Quality: 0)" Ansible is more specialized. Also using provisioners is a "last resort". @@ -448,14 +679,14 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w ### Scenario #3 In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. -This node template is implemented by its deployment artifact "artifact" of artifact type [zip.archive](/normative#ziparchive){target=_blank}. +This node template is implemented by its deployment artifact "artifact" of artifact type [tar.archive](/normative#tararchive){target=_blank}. The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. -
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
+
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
!!! info "Ansible (Quality: 0.5)" - While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. + While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application". !!! failure "Terraform (Quality: 0)" Ansible is more specialized. Also using provisioners is a "last resort". @@ -465,12 +696,15 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w ### Scenario #4 In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. -This node template is implemented by its deployment artifact "artifact" of artifact type [apt.archive](/normative#aptarchive){target=_blank}. +This node template is implemented by its deployment artifact "artifact" of artifact type [zip.archive](/normative#ziparchive){target=_blank}. The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. -
component(software.application)artifact(apt.archive)...host 2(remote.machine)hosthost
+
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
+!!! info "Ansible (Quality: 0.5)" + While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. + !!! failure "Terraform (Quality: 0)" Ansible is more specialized. Also using provisioners is a "last resort". @@ -503,319 +737,291 @@ The node template is hosted on the node template "host 1" of node type [openstac This appendix contains the deployment technology rules. - ### Rule #1 | Attribute | Value | | --- | --- | -| Identifier | docker.engine::ansible@remote.machine | -| Component | [docker.engine](/normative#dockerengine){target=_blank} | -| Hosting | [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 1 | -| Reason | Primary use case due to the specialization of Ansible. | -| Details | "ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks | -| Graph |
component(docker.engine)host 1(remote.machine)host
| +| Identifier | bucket::ansible@gcp.cloudstorage | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [gcp.cloudstorage](/normative#gcpcloudstorage){target=_blank} | +| Quality | 0.5 | +| Reason | Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. | +| Details | | +| Graph |
component(bucket)host 1(gcp.cloudstorage)host
| ### Rule #2 | Attribute | Value | | --- | --- | -| Identifier | gcp.service::ansible | -| Component | [gcp.service](/normative#gcpservice){target=_blank} | +| Identifier | bucket::terraform@gcp.cloudstorage | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [gcp.cloudstorage](/normative#gcpcloudstorage){target=_blank} | | Quality | 1 | -| Reason | Ansible provides a declarative module | -| Details | "google.cloud.gcp_serviceusage_service" task | -| Graph |
component(gcp.service)
| +| Reason | Terraform provides a declarative module. | +| Details | | +| Graph |
component(bucket)host 1(gcp.cloudstorage)host
| ### Rule #3 | Attribute | Value | | --- | --- | -| Identifier | ingress::ansible@kubernetes.cluster | -| Component | [ingress](/normative#ingress){target=_blank} | -| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | -| Quality | 0.5 | -| Reason | Kubernetes is more specialized. | -| Details | "kubernetes.core.k8s" task | -| Graph |
component(ingress)host 1(kubernetes.cluster)host
| +| Identifier | bucket::ansible@minio.server->*->local.machine | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [minio.server](/normative#minioserver){target=_blank} -> * -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | | +| Graph |
component(bucket)host 1(minio.server)...host 3(local.machine)hosthosthost
| ### Rule #4 | Attribute | Value | | --- | --- | -| Identifier | ingress::ansible@remote.machine | -| Component | [ingress](/normative#ingress){target=_blank} | -| Hosting | [remote.machine](/normative#remotemachine){target=_blank} | +| Identifier | bucket::terraform@minio.server->*->local.machine | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [minio.server](/normative#minioserver){target=_blank} -> * -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 1 | -| Reason | Primary use case due to the specialization of Ansible. | -| Details | "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", "ansible.builtin.copy", and "ansible.builtin.systemd" tasks | -| Graph |
component(ingress)host 1(remote.machine)host
| +| Reason | Terraform provides a declarative module. | +| Details | | +| Graph |
component(bucket)host 1(minio.server)...host 3(local.machine)hosthosthost
| ### Rule #5 | Attribute | Value | | --- | --- | -| Identifier | mysql.database::ansible@mysql.dbms->docker.engine->remote.machine | -| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | -| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Identifier | bucket::ansible@minio.server->*->remote.machine | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [minio.server](/normative#minioserver){target=_blank} -> * -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | | -| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(remote.machine)hosthosthost
| +| Graph |
component(bucket)host 1(minio.server)...host 3(remote.machine)hosthosthost
| ### Rule #6 | Attribute | Value | | --- | --- | -| Identifier | mysql.database::ansible@mysql.dbms->gcp.cloudsql | -| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | -| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [gcp.cloudsql](/normative#gcpcloudsql){target=_blank} | -| Quality | 0.5 | -| Reason | Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. | +| Identifier | bucket::terraform@minio.server->*->remote.machine | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [minio.server](/normative#minioserver){target=_blank} -> * -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Terraform provides a declarative module. | | Details | | -| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(gcp.cloudsql)hosthost
| +| Graph |
component(bucket)host 1(minio.server)...host 3(remote.machine)hosthosthost
| ### Rule #7 | Attribute | Value | | --- | --- | -| Identifier | mysql.database::ansible@mysql.dbms->kubernetes.cluster | -| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | -| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Identifier | bucket::ansible@minio.server->kubernetes.cluster | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [minio.server](/normative#minioserver){target=_blank} -> [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | | -| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(kubernetes.cluster)hosthost
| +| Graph |
component(bucket)host 1(minio.server)host 2(kubernetes.cluster)hosthost
| ### Rule #8 | Attribute | Value | | --- | --- | -| Identifier | mysql.database::ansible@mysql.dbms->remote.machine | -| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | -| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Identifier | bucket::terraform@minio.server->kubernetes.cluster | +| Component | [bucket](/normative#bucket){target=_blank} | +| Hosting | [minio.server](/normative#minioserver){target=_blank} -> [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 1 | -| Reason | Primary use case due to the specialization of Ansible. | +| Reason | Terraform provides a declarative module. | | Details | | -| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(remote.machine)hosthost
| +| Graph |
component(bucket)host 1(minio.server)host 2(kubernetes.cluster)hosthost
| ### Rule #9 | Attribute | Value | | --- | --- | -| Identifier | mysql.dbms#dbms.image::ansible@docker.engine->remote.machine | -| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | -| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | -| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 0.5 | -| Reason | Docker Compose is more specialized | -| Details | "community.docker.docker_container" task | -| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(remote.machine)hosthost
| +| Identifier | docker.engine::ansible@local.machine | +| Component | [docker.engine](/normative#dockerengine){target=_blank} | +| Hosting | [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | "ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks | +| Graph |
component(docker.engine)host 1(local.machine)host
| ### Rule #10 | Attribute | Value | | --- | --- | -| Identifier | mysql.dbms#dbms.image::ansible@gcp.cloudsql | -| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | -| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | -| Hosting | [gcp.cloudsql](/normative#gcpcloudsql){target=_blank} | -| Quality | 1 | -| Reason | Primary use case due to the specialization of Ansible. | -| Details | "google.cloud.gcp_sql_instance" and "google.cloud.gcp_sql_user" tasks | -| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(gcp.cloudsql)host
| +| Identifier | docker.engine::terraform@local.machine | +| Component | [docker.engine](/normative#dockerengine){target=_blank} | +| Hosting | [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0 | +| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | +| Details | "local-exec" provider | +| Graph |
component(docker.engine)host 1(local.machine)host
| ### Rule #11 | Attribute | Value | | --- | --- | -| Identifier | mysql.dbms#dbms.image::ansible@kubernetes.cluster | -| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | -| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | -| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | -| Quality | 0.5 | -| Reason | Kubernetes is more specialized. | -| Details | "kubernetes.core.k8s" tasks | -| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(kubernetes.cluster)host
| +| Identifier | docker.engine::ansible@remote.machine | +| Component | [docker.engine](/normative#dockerengine){target=_blank} | +| Hosting | [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | "ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks | +| Graph |
component(docker.engine)host 1(remote.machine)host
| ### Rule #12 | Attribute | Value | | --- | --- | -| Identifier | mysql.dbms#dbms.image::ansible@remote.machine | -| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | -| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Identifier | docker.engine::terraform@remote.machine | +| Component | [docker.engine](/normative#dockerengine){target=_blank} | | Hosting | [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 1 | -| Reason | Primary use case due to the specialization of Ansible. | -| Details | "ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks | -| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(remote.machine)host
| +| Quality | 0 | +| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | +| Details | "remote-exec" provider | +| Graph |
component(docker.engine)host 1(remote.machine)host
| ### Rule #13 | Attribute | Value | | --- | --- | -| Identifier | service.application#docker.image::ansible@docker.engine->remote.machine | -| Component | [service.application](/normative#serviceapplication){target=_blank} | -| Artifact | [docker.image](/normative#dockerimage){target=_blank} | -| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 0.5 | -| Reason | Docker Compose is more specialized. | -| Details | "community.docker.docker_container" task | -| Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
| +| Identifier | gcp.service::ansible | +| Component | [gcp.service](/normative#gcpservice){target=_blank} | +| Quality | 1 | +| Reason | Ansible provides a declarative module | +| Details | "google.cloud.gcp_serviceusage_service" task | +| Graph |
component(gcp.service)
| ### Rule #14 | Attribute | Value | | --- | --- | -| Identifier | service.application#docker.image::ansible@gcp.cloudrun | -| Component | [service.application](/normative#serviceapplication){target=_blank} | -| Artifact | [docker.image](/normative#dockerimage){target=_blank} | -| Hosting | [gcp.cloudrun](/normative#gcpcloudrun){target=_blank} | -| Quality | 0 | -| Reason | Custom module with imperative parts, while Terraform provides a declarative module. | -| Details | "ansible.builtin.shell", "ansible.builtin.tempfile", and "ansible.builtin.copy" tasks | -| Graph |
component(service.application)artifact(docker.image)host 1(gcp.cloudrun)host
| +| Identifier | gcp.service::terraform | +| Component | [gcp.service](/normative#gcpservice){target=_blank} | +| Quality | 1 | +| Reason | Terraform provides a declarative module. | +| Details | "google_project_service" resource | +| Graph |
component(gcp.service)
| ### Rule #15 | Attribute | Value | | --- | --- | -| Identifier | service.application#docker.image::ansible@kubernetes.cluster | -| Component | [service.application](/normative#serviceapplication){target=_blank} | -| Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Identifier | ingress::ansible@kubernetes.cluster | +| Component | [ingress](/normative#ingress){target=_blank} | | Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 0.5 | | Reason | Kubernetes is more specialized. | -| Details | "kubernetes.core.k8s" tasks | -| Graph |
component(service.application)artifact(docker.image)host 1(kubernetes.cluster)host
| +| Details | "kubernetes.core.k8s" task | +| Graph |
component(ingress)host 1(kubernetes.cluster)host
| ### Rule #16 | Attribute | Value | | --- | --- | -| Identifier | service.application#tar.archive::ansible@*->remote.machine | -| Component | [service.application](/normative#serviceapplication){target=_blank} | -| Artifact | [tar.archive](/normative#tararchive){target=_blank} | -| Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | +| Identifier | ingress::kubernetes@kubernetes.cluster | +| Component | [ingress](/normative#ingress){target=_blank} | +| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 1 | -| Reason | Primary use case due to the specialization of Ansible. Special integration for systemd. | -| Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements | -| Graph |
component(service.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| +| Reason | Kubernetes is the underlying technology. | +| Details | Kubernetes manifest generated and applied | +| Graph |
component(ingress)host 1(kubernetes.cluster)host
| ### Rule #17 | Attribute | Value | | --- | --- | -| Identifier | service.application#zip.archive::ansible@*->remote.machine | -| Component | [service.application](/normative#serviceapplication){target=_blank} | -| Artifact | [zip.archive](/normative#ziparchive){target=_blank} | -| Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 1 | -| Reason | Primary use case due to the specialization of Ansible. Special integration for systemd. | -| Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements | -| Graph |
component(service.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| +| Identifier | ingress::terraform@kubernetes.cluster | +| Component | [ingress](/normative#ingress){target=_blank} | +| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Quality | 0.5 | +| Reason | Kubernetes is more specialized. | +| Details | "kubernetes_service_v1" resource | +| Graph |
component(ingress)host 1(kubernetes.cluster)host
| ### Rule #18 | Attribute | Value | | --- | --- | -| Identifier | service.application#zip.archive::ansible@gcp.appengine | -| Component | [service.application](/normative#serviceapplication){target=_blank} | -| Artifact | [zip.archive](/normative#ziparchive){target=_blank} | -| Hosting | [gcp.appengine](/normative#gcpappengine){target=_blank} | -| Quality | 0 | -| Reason | Custom module with imperative parts, while Terraform provides a declarative module. | -| Details | "ansible.builtin.shell", "ansible.builtin.tempfile", "ansible.builtin.unarchive", and "ansible.builtin.copy" tasks | -| Graph |
component(service.application)artifact(zip.archive)host 1(gcp.appengine)host
| +| Identifier | ingress::ansible@remote.machine | +| Component | [ingress](/normative#ingress){target=_blank} | +| Hosting | [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", "ansible.builtin.copy", and "ansible.builtin.systemd" tasks | +| Graph |
component(ingress)host 1(remote.machine)host
| ### Rule #19 | Attribute | Value | | --- | --- | -| Identifier | software.application#apt.package::ansible@*->remote.machine | -| Component | [software.application](/normative#softwareapplication){target=_blank} | -| Artifact | [apt.package](/normative#aptpackage){target=_blank} | -| Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 1 | -| Reason | Primary use case due to the specialization of Ansible. | -| Details | "ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements | -| Graph |
component(software.application)artifact(apt.package)...host 2(remote.machine)hosthost
| +| Identifier | ingress::terraform@remote.machine | +| Component | [ingress](/normative#ingress){target=_blank} | +| Hosting | [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 0 | +| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | +| Details | "terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner | +| Graph |
component(ingress)host 1(remote.machine)host
| ### Rule #20 | Attribute | Value | | --- | --- | -| Identifier | software.application#tar.archive::ansible@*->remote.machine | -| Component | [software.application](/normative#softwareapplication){target=_blank} | -| Artifact | [tar.archive](/normative#tararchive){target=_blank} | -| Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 0.5 | -| Reason | While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application". | -| Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | -| Graph |
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| +| Identifier | mysql.database::ansible@mysql.dbms->docker.engine->local.machine | +| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | | +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(local.machine)hosthosthost
| ### Rule #21 | Attribute | Value | | --- | --- | -| Identifier | software.application#zip.archive::ansible@*->remote.machine | -| Component | [software.application](/normative#softwareapplication){target=_blank} | -| Artifact | [zip.archive](/normative#ziparchive){target=_blank} | -| Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 0.5 | -| Reason | While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. | -| Details | "ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | -| Graph |
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| +| Identifier | mysql.database::compose@mysql.dbms->docker.engine->local.machine | +| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0 | +| Reason | One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. | +| Details | | +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(local.machine)hosthosthost
| ### Rule #22 | Attribute | Value | | --- | --- | -| Identifier | virtual.machine#machine.image::ansible@openstack.provider | -| Component | [virtual.machine](/normative#virtualmachine){target=_blank} | -| Artifact | [machine.image](/normative#machineimage){target=_blank} | -| Hosting | [openstack.provider](/normative#openstackprovider){target=_blank} | +| Identifier | mysql.database::terraform@mysql.dbms->docker.engine->local.machine | +| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0.5 | -| Reason | Terraform is more specialized. | -| Details | "openstack.cloud.security_group", "openstack.cloud.security_group_rule" and "openstack.cloud.server" tasks | -| Graph |
component(virtual.machine)artifact(machine.image)host 1(openstack.provider)host
| - - +| Reason | Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. | +| Details | | +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(local.machine)hosthosthost
| ### Rule #23 | Attribute | Value | | --- | --- | -| Identifier | docker.engine::terraform@remote.machine | -| Component | [docker.engine](/normative#dockerengine){target=_blank} | -| Hosting | [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 0 | -| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | -| Details | "remote-exec" provider | -| Graph |
component(docker.engine)host 1(remote.machine)host
| +| Identifier | mysql.database::ansible@mysql.dbms->docker.engine->remote.machine | +| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | | +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(remote.machine)hosthosthost
| ### Rule #24 | Attribute | Value | | --- | --- | -| Identifier | gcp.service::terraform | -| Component | [gcp.service](/normative#gcpservice){target=_blank} | -| Quality | 1 | -| Reason | Terraform provides a declarative module. | -| Details | "google_project_service" resource | -| Graph |
component(gcp.service)
| +| Identifier | mysql.database::compose@mysql.dbms->docker.engine->remote.machine | +| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 0 | +| Reason | One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. | +| Details | | +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(remote.machine)hosthosthost
| ### Rule #25 | Attribute | Value | | --- | --- | -| Identifier | ingress::terraform@kubernetes.cluster | -| Component | [ingress](/normative#ingress){target=_blank} | -| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Identifier | mysql.database::terraform@mysql.dbms->docker.engine->remote.machine | +| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0.5 | -| Reason | Kubernetes is more specialized. | -| Details | "kubernetes_service_v1" resource | -| Graph |
component(ingress)host 1(kubernetes.cluster)host
| +| Reason | Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. | +| Details | | +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(remote.machine)hosthosthost
| ### Rule #26 | Attribute | Value | | --- | --- | -| Identifier | ingress::terraform@remote.machine | -| Component | [ingress](/normative#ingress){target=_blank} | -| Hosting | [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 0 | -| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | -| Details | "terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner | -| Graph |
component(ingress)host 1(remote.machine)host
| - -### Rule #27 -| Attribute | Value | -| --- | --- | -| Identifier | mysql.database::terraform@mysql.dbms->docker.engine->remote.machine | +| Identifier | mysql.database::ansible@mysql.dbms->gcp.cloudsql | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | -| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [gcp.cloudsql](/normative#gcpcloudsql){target=_blank} | | Quality | 0.5 | -| Reason | Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. | +| Reason | Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. | | Details | | -| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(remote.machine)hosthosthost
| +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(gcp.cloudsql)hosthost
| -### Rule #28 +### Rule #27 | Attribute | Value | | --- | --- | | Identifier | mysql.database::terraform@mysql.dbms->gcp.cloudsql | @@ -826,9 +1032,31 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(gcp.cloudsql)hosthost
| +### Rule #28 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.database::ansible@mysql.dbms->kubernetes.cluster | +| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | | +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(kubernetes.cluster)hosthost
| + ### Rule #29 | Attribute | Value | | --- | --- | +| Identifier | mysql.database::kubernetes@mysql.dbms->kubernetes.cluster | +| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Quality | 0 | +| Reason | Kubernetes Job with imperative parts, while declarative other technologies provide declarative modules. | +| Details | | +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(kubernetes.cluster)hosthost
| + +### Rule #30 +| Attribute | Value | +| --- | --- | | Identifier | mysql.database::terraform@mysql.dbms->kubernetes.cluster | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | @@ -837,7 +1065,18 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(kubernetes.cluster)hosthost
| -### Rule #30 +### Rule #31 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.database::ansible@mysql.dbms->remote.machine | +| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | | +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(remote.machine)hosthost
| + +### Rule #32 | Attribute | Value | | --- | --- | | Identifier | mysql.database::terraform@mysql.dbms->remote.machine | @@ -848,7 +1087,67 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(remote.machine)hosthost
| -### Rule #31 +### Rule #33 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::ansible@docker.engine->local.machine | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized | +| Details | "community.docker.docker_container" task | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #34 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::compose@docker.engine->local.machine | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Docker is the underlying technology. | +| Details | docker-compose manifest generated and applied | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #35 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::terraform@docker.engine->local.machine | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized. | +| Details | "docker_container" and "docker_image" resources | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #36 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::ansible@docker.engine->remote.machine | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized | +| Details | "community.docker.docker_container" task | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(remote.machine)hosthost
| + +### Rule #37 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::compose@docker.engine->remote.machine | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Docker is the underlying technology. | +| Details | docker-compose manifest generated and applied | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(remote.machine)hosthost
| + +### Rule #38 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::terraform@docker.engine->remote.machine | @@ -860,43 +1159,271 @@ This appendix contains the deployment technology rules. | Details | "docker_container" and "docker_image" resources | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #32 +### Rule #39 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::ansible@gcp.cloudsql | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [gcp.cloudsql](/normative#gcpcloudsql){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | "google.cloud.gcp_sql_instance" and "google.cloud.gcp_sql_user" tasks | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(gcp.cloudsql)host
| + +### Rule #40 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::terraform@gcp.cloudsql | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [gcp.cloudsql](/normative#gcpcloudsql){target=_blank} | +| Quality | 1 | +| Reason | Terraform provides a declarative module. | +| Details | "google_sql_database_instance" and "google_sql_user" resources | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(gcp.cloudsql)host
| + +### Rule #41 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::ansible@kubernetes.cluster | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Quality | 0.5 | +| Reason | Kubernetes is more specialized. | +| Details | "kubernetes.core.k8s" tasks | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(kubernetes.cluster)host
| + +### Rule #42 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::kubernetes@kubernetes.cluster | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Quality | 1 | +| Reason | Kubernetes is the underlying technology. | +| Details | Kubernetes manifest generated and applied | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(kubernetes.cluster)host
| + +### Rule #43 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::terraform@kubernetes.cluster | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Quality | 0.5 | +| Reason | Kubernetes is more specialized. | +| Details | "kubernetes_deployment_v1" and "kubernetes_service_v1" resources | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(kubernetes.cluster)host
| + +### Rule #44 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::ansible@remote.machine | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | "ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(remote.machine)host
| + +### Rule #45 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::terraform@remote.machine | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 0 | +| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | +| Details | "terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(remote.machine)host
| + +### Rule #46 +| Attribute | Value | +| --- | --- | +| Identifier | bucket#cache.image::ansible@gcp.memorystore | +| Component | [bucket](/normative#bucket){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [gcp.memorystore](/normative#gcpmemorystore){target=_blank} | +| Quality | 0.5 | +| Reason | Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. | +| Details | | +| Graph |
component(bucket)artifact(cache.image)host 1(gcp.memorystore)host
| + +### Rule #47 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::terraform@gcp.memorystore | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [gcp.memorystore](/normative#gcpmemorystore){target=_blank} | +| Quality | 1 | +| Reason | Terraform provides a declarative module. | +| Details | | +| Graph |
component(redis.server)artifact(cache.image)host 1(gcp.memorystore)host
| + +### Rule #48 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::ansible@docker.engine->local.machine | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized. | +| Details | "community.docker.docker_container" task | +| Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #49 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::compose@docker.engine->local.machine | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Docker is the underlying technology. | +| Details | docker compose manifest generated and applied | +| Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #50 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::terraform@docker.engine->local.machine | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized. | +| Details | "docker_container" and "docker_image" resources | +| Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #51 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::ansible@docker.engine->remote.machine | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized. | +| Details | "community.docker.docker_container" task | +| Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(remote.machine)hosthost
| + +### Rule #52 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::compose@docker.engine->remote.machine | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Docker is the underlying technology. | +| Details | docker compose manifest generated and applied | +| Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(remote.machine)hosthost
| + +### Rule #53 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::terraform@docker.engine->remote.machine | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized. | +| Details | "docker_container" and "docker_image" resources | +| Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(remote.machine)hosthost
| + +### Rule #54 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::ansible@kubernetes.cluster | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | | +| Graph |
component(redis.server)artifact(cache.image)host 1(kubernetes.cluster)host
| + +### Rule #55 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::terraform@kubernetes.cluster | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Quality | 1 | +| Reason | Terraform provides a declarative module. | +| Details | | +| Graph |
component(redis.server)artifact(cache.image)host 1(kubernetes.cluster)host
| + +### Rule #56 +| Attribute | Value | +| --- | --- | +| Identifier | service.application#docker.image::ansible@docker.engine->local.machine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized. | +| Details | "community.docker.docker_container" task | +| Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #57 +| Attribute | Value | +| --- | --- | +| Identifier | service.application#docker.image::compose@docker.engine->local.machine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Docker is the underlying technology. | +| Details | docker compose manifest generated and applied | +| Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(local.machine)hosthost
| + +### Rule #58 | Attribute | Value | | --- | --- | -| Identifier | mysql.dbms#dbms.image::terraform@gcp.cloudsql | -| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | -| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | -| Hosting | [gcp.cloudsql](/normative#gcpcloudsql){target=_blank} | -| Quality | 1 | -| Reason | Terraform provides a declarative module. | -| Details | "google_sql_database_instance" and "google_sql_user" resources | -| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(gcp.cloudsql)host
| +| Identifier | service.application#docker.image::terraform@docker.engine->local.machine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | Docker Compose is more specialized. | +| Details | "docker_container" and "docker_image" resources | +| Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #33 +### Rule #59 | Attribute | Value | | --- | --- | -| Identifier | mysql.dbms#dbms.image::terraform@kubernetes.cluster | -| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | -| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | -| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Identifier | service.application#docker.image::ansible@docker.engine->remote.machine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0.5 | -| Reason | Kubernetes is more specialized. | -| Details | "kubernetes_deployment_v1" and "kubernetes_service_v1" resources | -| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(kubernetes.cluster)host
| +| Reason | Docker Compose is more specialized. | +| Details | "community.docker.docker_container" task | +| Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #34 +### Rule #60 | Attribute | Value | | --- | --- | -| Identifier | mysql.dbms#dbms.image::terraform@remote.machine | -| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | -| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | -| Hosting | [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 0 | -| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | -| Details | "terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner | -| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(remote.machine)host
| +| Identifier | service.application#docker.image::compose@docker.engine->remote.machine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Docker is the underlying technology. | +| Details | docker compose manifest generated and applied | +| Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #35 +### Rule #61 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::terraform@docker.engine->remote.machine | @@ -908,7 +1435,19 @@ This appendix contains the deployment technology rules. | Details | "docker_container" and "docker_image" resources | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #36 +### Rule #62 +| Attribute | Value | +| --- | --- | +| Identifier | service.application#docker.image::ansible@gcp.cloudrun | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Hosting | [gcp.cloudrun](/normative#gcpcloudrun){target=_blank} | +| Quality | 0 | +| Reason | Custom module with imperative parts, while Terraform provides a declarative module. | +| Details | "ansible.builtin.shell", "ansible.builtin.tempfile", and "ansible.builtin.copy" tasks | +| Graph |
component(service.application)artifact(docker.image)host 1(gcp.cloudrun)host
| + +### Rule #63 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::terraform@gcp.cloudrun | @@ -920,7 +1459,31 @@ This appendix contains the deployment technology rules. | Details | "google_cloud_run_v2_service" and "google_cloud_run_service_iam_binding" resources | | Graph |
component(service.application)artifact(docker.image)host 1(gcp.cloudrun)host
| -### Rule #37 +### Rule #64 +| Attribute | Value | +| --- | --- | +| Identifier | service.application#docker.image::ansible@kubernetes.cluster | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Quality | 0.5 | +| Reason | Kubernetes is more specialized. | +| Details | "kubernetes.core.k8s" tasks | +| Graph |
component(service.application)artifact(docker.image)host 1(kubernetes.cluster)host
| + +### Rule #65 +| Attribute | Value | +| --- | --- | +| Identifier | service.application#docker.image::kubernetes@kubernetes.cluster | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | +| Quality | 1 | +| Reason | Kubernetes is the underlying technology. | +| Details | Kubernetes manifest generated and applied | +| Graph |
component(service.application)artifact(docker.image)host 1(kubernetes.cluster)host
| + +### Rule #66 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::terraform@kubernetes.cluster | @@ -932,7 +1495,19 @@ This appendix contains the deployment technology rules. | Details | "kubernetes_deployment_v1" and "kubernetes_service_v1" resources | | Graph |
component(service.application)artifact(docker.image)host 1(kubernetes.cluster)host
| -### Rule #38 +### Rule #67 +| Attribute | Value | +| --- | --- | +| Identifier | service.application#tar.archive::ansible@*->remote.machine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [tar.archive](/normative#tararchive){target=_blank} | +| Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. Special integration for systemd. | +| Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements | +| Graph |
component(service.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| + +### Rule #68 | Attribute | Value | | --- | --- | | Identifier | service.application#tar.archive::terraform@*->remote.machine | @@ -944,7 +1519,19 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(service.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #39 +### Rule #69 +| Attribute | Value | +| --- | --- | +| Identifier | service.application#zip.archive::ansible@*->remote.machine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. Special integration for systemd. | +| Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements | +| Graph |
component(service.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| + +### Rule #70 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::terraform@*->remote.machine | @@ -956,7 +1543,19 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(service.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #40 +### Rule #71 +| Attribute | Value | +| --- | --- | +| Identifier | service.application#zip.archive::ansible@gcp.appengine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Hosting | [gcp.appengine](/normative#gcpappengine){target=_blank} | +| Quality | 0 | +| Reason | Custom module with imperative parts, while Terraform provides a declarative module. | +| Details | "ansible.builtin.shell", "ansible.builtin.tempfile", "ansible.builtin.unarchive", and "ansible.builtin.copy" tasks | +| Graph |
component(service.application)artifact(zip.archive)host 1(gcp.appengine)host
| + +### Rule #72 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::terraform@gcp.appengine | @@ -968,7 +1567,19 @@ This appendix contains the deployment technology rules. | Details | "google_app_engine_standard_app_version", "google_project_iam_member", "google_service_account", "google_storage_bucket", and "google_storage_bucket_object" resources | | Graph |
component(service.application)artifact(zip.archive)host 1(gcp.appengine)host
| -### Rule #41 +### Rule #73 +| Attribute | Value | +| --- | --- | +| Identifier | software.application#apt.package::ansible@*->remote.machine | +| Component | [software.application](/normative#softwareapplication){target=_blank} | +| Artifact | [apt.package](/normative#aptpackage){target=_blank} | +| Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | "ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements | +| Graph |
component(software.application)artifact(apt.package)...host 2(remote.machine)hosthost
| + +### Rule #74 | Attribute | Value | | --- | --- | | Identifier | software.application#apt.archive::terraform@*->remote.machine | @@ -980,7 +1591,19 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload scripts and "remote-exec" to execute scripts | | Graph |
component(software.application)artifact(apt.archive)...host 2(remote.machine)hosthost
| -### Rule #42 +### Rule #75 +| Attribute | Value | +| --- | --- | +| Identifier | software.application#tar.archive::ansible@*->remote.machine | +| Component | [software.application](/normative#softwareapplication){target=_blank} | +| Artifact | [tar.archive](/normative#tararchive){target=_blank} | +| Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 0.5 | +| Reason | While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application". | +| Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | +| Graph |
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| + +### Rule #76 | Attribute | Value | | --- | --- | | Identifier | software.application#tar.archive::terraform@*->remote.machine | @@ -992,7 +1615,19 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #43 +### Rule #77 +| Attribute | Value | +| --- | --- | +| Identifier | software.application#zip.archive::ansible@*->remote.machine | +| Component | [software.application](/normative#softwareapplication){target=_blank} | +| Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 0.5 | +| Reason | While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. | +| Details | "ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | +| Graph |
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| + +### Rule #78 | Attribute | Value | | --- | --- | | Identifier | software.application#zip.archive::terraform@*->remote.machine | @@ -1004,103 +1639,29 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #44 +### Rule #79 | Attribute | Value | | --- | --- | -| Identifier | virtual.machine#machine.image::terraform@openstack.provider | +| Identifier | virtual.machine#machine.image::ansible@openstack.provider | | Component | [virtual.machine](/normative#virtualmachine){target=_blank} | | Artifact | [machine.image](/normative#machineimage){target=_blank} | | Hosting | [openstack.provider](/normative#openstackprovider){target=_blank} | -| Quality | 1 | -| Reason | Terraform provides a declarative module. | -| Details | "openstack_compute_instance_v2", "openstack_networking_secgroup_rule_v2" and "openstack_networking_secgroup_v2" resources | +| Quality | 0.5 | +| Reason | Terraform is more specialized. | +| Details | "openstack.cloud.security_group", "openstack.cloud.security_group_rule" and "openstack.cloud.server" tasks | | Graph |
component(virtual.machine)artifact(machine.image)host 1(openstack.provider)host
| - - -### Rule #45 -| Attribute | Value | -| --- | --- | -| Identifier | ingress::kubernetes@kubernetes.cluster | -| Component | [ingress](/normative#ingress){target=_blank} | -| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | -| Quality | 1 | -| Reason | Kubernetes is the underlying technology. | -| Details | Kubernetes manifest generated and applied | -| Graph |
component(ingress)host 1(kubernetes.cluster)host
| - -### Rule #46 -| Attribute | Value | -| --- | --- | -| Identifier | mysql.database::kubernetes@mysql.dbms->kubernetes.cluster | -| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | -| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | -| Quality | 0 | -| Reason | Kubernetes Job with imperative parts, while declarative other technologies provide declarative modules. | -| Details | | -| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(kubernetes.cluster)hosthost
| - -### Rule #47 -| Attribute | Value | -| --- | --- | -| Identifier | mysql.dbms#dbms.image::kubernetes@kubernetes.cluster | -| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | -| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | -| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | -| Quality | 1 | -| Reason | Kubernetes is the underlying technology. | -| Details | Kubernetes manifest generated and applied | -| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(kubernetes.cluster)host
| - -### Rule #48 -| Attribute | Value | -| --- | --- | -| Identifier | service.application#docker.image::kubernetes@kubernetes.cluster | -| Component | [service.application](/normative#serviceapplication){target=_blank} | -| Artifact | [docker.image](/normative#dockerimage){target=_blank} | -| Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | -| Quality | 1 | -| Reason | Kubernetes is the underlying technology. | -| Details | Kubernetes manifest generated and applied | -| Graph |
component(service.application)artifact(docker.image)host 1(kubernetes.cluster)host
| - - - -### Rule #49 -| Attribute | Value | -| --- | --- | -| Identifier | mysql.database::compose@mysql.dbms->docker.engine->remote.machine | -| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | -| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 0 | -| Reason | One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. | -| Details | | -| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(remote.machine)hosthosthost
| - -### Rule #50 -| Attribute | Value | -| --- | --- | -| Identifier | mysql.dbms#dbms.image::compose@docker.engine->remote.machine | -| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | -| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | -| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 1 | -| Reason | Docker is the underlying technology. | -| Details | docker-compose manifest generated and applied | -| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(remote.machine)hosthost
| - -### Rule #51 +### Rule #80 | Attribute | Value | | --- | --- | -| Identifier | service.application#docker.image::compose@docker.engine->remote.machine | -| Component | [service.application](/normative#serviceapplication){target=_blank} | -| Artifact | [docker.image](/normative#dockerimage){target=_blank} | -| Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | +| Identifier | virtual.machine#machine.image::terraform@openstack.provider | +| Component | [virtual.machine](/normative#virtualmachine){target=_blank} | +| Artifact | [machine.image](/normative#machineimage){target=_blank} | +| Hosting | [openstack.provider](/normative#openstackprovider){target=_blank} | | Quality | 1 | -| Reason | Docker is the underlying technology. | -| Details | docker compose manifest generated and applied | -| Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
| - +| Reason | Terraform provides a declarative module. | +| Details | "openstack_compute_instance_v2", "openstack_networking_secgroup_rule_v2" and "openstack_networking_secgroup_v2" resources | +| Graph |
component(virtual.machine)artifact(machine.image)host 1(openstack.provider)host
| diff --git a/docs/docs/variability4tosca/rules/technology-rules.yaml b/docs/docs/variability4tosca/rules/technology-rules.yaml index f58ff02c68..ef6540afa3 100644 --- a/docs/docs/variability4tosca/rules/technology-rules.yaml +++ b/docs/docs/variability4tosca/rules/technology-rules.yaml @@ -1,560 +1,638 @@ -ansible: - - component: bucket - hosting: - - gcp.cloudstorage - weight: 0.5 - reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. - - component: bucket - hosting: - - minio.server - - '*' - - local.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: bucket - hosting: - - minio.server - - '*' - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: bucket - hosting: - - minio.server - - kubernetes.cluster - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: docker.engine - hosting: - - local.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - details: '"ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks' - - component: docker.engine - hosting: - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - details: '"ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks' - - component: gcp.service - hosting: [] - weight: 1 - reason: Ansible provides a declarative module - details: '"google.cloud.gcp_serviceusage_service" task' - - component: ingress - hosting: - - kubernetes.cluster - weight: 0.5 - reason: Kubernetes is more specialized. - details: '"kubernetes.core.k8s" task' - - component: ingress - hosting: - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - details: '"ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", "ansible.builtin.copy", and "ansible.builtin.systemd" tasks' - - component: mysql.database - hosting: - - mysql.dbms - - docker.engine - - local.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: mysql.database - hosting: - - mysql.dbms - - docker.engine - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: mysql.database - hosting: - - mysql.dbms - - gcp.cloudsql - weight: 0.5 - reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. - - component: mysql.database - hosting: - - mysql.dbms - - kubernetes.cluster - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: mysql.database - hosting: - - mysql.dbms - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: mysql.dbms - artifact: dbms.image - hosting: - - docker.engine - - local.machine - weight: 0.5 - reason: Docker Compose is more specialized - details: '"community.docker.docker_container" task' - - component: mysql.dbms - artifact: dbms.image - hosting: - - docker.engine - - remote.machine - weight: 0.5 - reason: Docker Compose is more specialized - details: '"community.docker.docker_container" task' - - component: mysql.dbms - artifact: dbms.image - hosting: - - gcp.cloudsql - weight: 1 - reason: Primary use case due to the specialization of Ansible. - details: '"google.cloud.gcp_sql_instance" and "google.cloud.gcp_sql_user" tasks' - - component: mysql.dbms - artifact: dbms.image - hosting: - - kubernetes.cluster - weight: 0.5 - reason: Kubernetes is more specialized. - details: '"kubernetes.core.k8s" tasks' - - component: mysql.dbms - artifact: dbms.image - hosting: - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - details: '"ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks' - - component: bucket - artifact: cache.image - hosting: - - gcp.memorystore - weight: 0.5 - reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. - - component: redis.server - artifact: cache.image - hosting: - - docker.engine - - local.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"community.docker.docker_container" task' - - component: redis.server - artifact: cache.image - hosting: - - docker.engine - - remote.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"community.docker.docker_container" task' - - component: redis.server - hosting: - - kubernetes.cluster - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: service.application - artifact: docker.image - hosting: - - docker.engine - - local.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"community.docker.docker_container" task' - - component: service.application - artifact: docker.image - hosting: - - docker.engine - - remote.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"community.docker.docker_container" task' - - component: service.application - artifact: docker.image - hosting: - - gcp.cloudrun - weight: 0 - reason: Custom module with imperative parts, while Terraform provides a declarative module. - details: '"ansible.builtin.shell", "ansible.builtin.tempfile", and "ansible.builtin.copy" tasks ' - - component: service.application - artifact: docker.image - hosting: - - kubernetes.cluster - weight: 0.5 - reason: Kubernetes is more specialized. - details: '"kubernetes.core.k8s" tasks' - - component: service.application - artifact: tar.archive - hosting: - - '*' - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. Special integration for systemd. - details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements' - - component: service.application - artifact: zip.archive - hosting: - - '*' - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. Special integration for systemd. - details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements' - - component: service.application - artifact: zip.archive - hosting: - - gcp.appengine - weight: 0 - reason: Custom module with imperative parts, while Terraform provides a declarative module. - details: '"ansible.builtin.shell", "ansible.builtin.tempfile", "ansible.builtin.unarchive", and "ansible.builtin.copy" tasks' - - component: software.application - artifact: apt.package - hosting: - - '*' - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - details: '"ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements' - - component: software.application - artifact: tar.archive - hosting: - - '*' - - remote.machine - weight: 0.5 - reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application". - details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' - - component: software.application - artifact: zip.archive - hosting: - - '*' - - remote.machine - weight: 0.5 - reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. - details: '"ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' - - component: virtual.machine - artifact: machine.image - hosting: - - openstack.provider - weight: 0.5 - reason: Terraform is more specialized. - details: '"openstack.cloud.security_group", "openstack.cloud.security_group_rule" and "openstack.cloud.server" tasks' -terraform: - - component: bucket - hosting: - - gcp.cloudstorage - weight: 1 - reason: Terraform provides a declarative module. - - component: bucket - hosting: - - minio.server - - '*' - - local.machine - weight: 1 - reason: Terraform provides a declarative module. - - component: bucket - hosting: - - minio.server - - '*' - - remote.machine - weight: 1 - reason: Terraform provides a declarative module. - - component: bucket - hosting: - - minio.server - - kubernetes.cluster - weight: 1 - reason: Terraform provides a declarative module. - - component: docker.engine - hosting: - - local.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"local-exec" provider' - - component: docker.engine - hosting: - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"remote-exec" provider' - - component: gcp.service - hosting: [] - weight: 1 - reason: Terraform provides a declarative module. - details: '"google_project_service" resource' - - component: ingress - hosting: - - kubernetes.cluster - weight: 0.5 - reason: Kubernetes is more specialized. - details: '"kubernetes_service_v1" resource' - - component: ingress - hosting: - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' - - component: mysql.database - hosting: - - mysql.dbms - - docker.engine - - local.machine - weight: 0.5 - reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. - - component: mysql.database - hosting: - - mysql.dbms - - docker.engine - - remote.machine - weight: 0.5 - reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. - - component: mysql.database - hosting: - - mysql.dbms - - gcp.cloudsql - weight: 1 - reason: Terraform provides a declarative module. - - component: mysql.database - hosting: - - mysql.dbms - - kubernetes.cluster - weight: 0 - reason: Ansible is more specialized. - - component: mysql.database - hosting: - - mysql.dbms - - remote.machine - weight: 0.5 - reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. - - component: mysql.dbms - artifact: dbms.image - hosting: - - docker.engine - - local.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"docker_container" and "docker_image" resources' - - component: mysql.dbms - artifact: dbms.image - hosting: - - docker.engine - - remote.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"docker_container" and "docker_image" resources' - - component: mysql.dbms - artifact: dbms.image - hosting: - - gcp.cloudsql - weight: 1 - reason: Terraform provides a declarative module. - details: '"google_sql_database_instance" and "google_sql_user" resources' - - component: mysql.dbms - artifact: dbms.image - hosting: - - kubernetes.cluster - weight: 0.5 - reason: Kubernetes is more specialized. - details: '"kubernetes_deployment_v1" and "kubernetes_service_v1" resources' - - component: mysql.dbms - artifact: dbms.image - hosting: - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' - - component: redis.server - artifact: cache.image - hosting: - - gcp.memorystore - weight: 1 - reason: Terraform provides a declarative module. - - component: redis.server - artifact: cache.image - hosting: - - docker.engine - - local.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"docker_container" and "docker_image" resources' - - component: redis.server - artifact: cache.image - hosting: - - docker.engine - - remote.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"docker_container" and "docker_image" resources' - - component: redis.server - hosting: - - kubernetes.cluster - weight: 1 - reason: Terraform provides a declarative module. - - component: service.application - artifact: docker.image - hosting: - - docker.engine - - local.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"docker_container" and "docker_image" resources' - - component: service.application - artifact: docker.image - hosting: - - docker.engine - - remote.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"docker_container" and "docker_image" resources' - - component: service.application - artifact: docker.image - hosting: - - gcp.cloudrun - weight: 1 - reason: Terraform provides a declarative module. - details: '"google_cloud_run_v2_service" and "google_cloud_run_service_iam_binding" resources' - - component: service.application - artifact: docker.image - hosting: - - kubernetes.cluster - weight: 0.5 - reason: Kubernetes is more specialized. - details: '"kubernetes_deployment_v1" and "kubernetes_service_v1" resources' - - component: service.application - artifact: tar.archive - hosting: - - '*' - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' - - component: service.application - artifact: zip.archive - hosting: - - '*' - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' - - component: service.application - artifact: zip.archive - hosting: - - gcp.appengine - weight: 1 - reason: Terraform provides a declarative module. - details: '"google_app_engine_standard_app_version", "google_project_iam_member", "google_service_account", "google_storage_bucket", and "google_storage_bucket_object" resources' - - component: software.application - artifact: apt.archive - hosting: - - '*' - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"file" provisioner to upload scripts and "remote-exec" to execute scripts' - - component: software.application - artifact: tar.archive - hosting: - - '*' - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' - - component: software.application - artifact: zip.archive - hosting: - - '*' - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' - - component: virtual.machine - artifact: machine.image - hosting: - - openstack.provider - weight: 1 - reason: Terraform provides a declarative module. - details: '"openstack_compute_instance_v2", "openstack_networking_secgroup_rule_v2" and "openstack_networking_secgroup_v2" resources' -kubernetes: - - component: ingress - hosting: - - kubernetes.cluster - weight: 1 - reason: Kubernetes is the underlying technology. - details: Kubernetes manifest generated and applied - - component: mysql.database - hosting: - - mysql.dbms - - kubernetes.cluster - weight: 0 - reason: Kubernetes Job with imperative parts, while declarative other technologies provide declarative modules. - - component: mysql.dbms - artifact: dbms.image - hosting: - - kubernetes.cluster - weight: 1 - reason: Kubernetes is the underlying technology. - details: Kubernetes manifest generated and applied - - component: service.application - artifact: docker.image - hosting: - - kubernetes.cluster - weight: 1 - reason: Kubernetes is the underlying technology. - details: Kubernetes manifest generated and applied -compose: - - component: mysql.database - hosting: - - mysql.dbms - - docker.engine - - local.machine - weight: 0 - reason: One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. - - component: mysql.database - 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. - - component: mysql.dbms - artifact: dbms.image - hosting: - - docker.engine - - local.machine - weight: 1 - reason: Docker is the underlying technology. - details: docker-compose manifest generated and applied - - component: mysql.dbms - artifact: dbms.image - hosting: - - docker.engine - - remote.machine - weight: 1 - reason: Docker is the underlying technology. - details: docker-compose manifest generated and applied - - component: redis.server - artifact: cache.image - hosting: - - docker.engine - - local.machine - weight: 1 - reason: Docker is the underlying technology. - details: docker compose manifest generated and applied - - component: redis.server - artifact: cache.image - hosting: - - docker.engine - - remote.machine - weight: 1 - reason: Docker is the underlying technology. - details: docker compose manifest generated and applied - - component: service.application - artifact: docker.image - hosting: - - docker.engine - - local.machine - weight: 1 - reason: Docker is the underlying technology. - details: docker compose manifest generated and applied - - component: service.application - artifact: docker.image - hosting: - - docker.engine - - remote.machine - weight: 1 - reason: Docker is the underlying technology. - details: docker compose manifest generated and applied +- technology: ansible + component: bucket + hosting: + - gcp.cloudstorage + weight: 0.5 + reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. +- technology: terraform + component: bucket + hosting: + - gcp.cloudstorage + weight: 1 + reason: Terraform provides a declarative module. +- technology: ansible + component: bucket + hosting: + - minio.server + - '*' + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. +- technology: terraform + component: bucket + hosting: + - minio.server + - '*' + - local.machine + weight: 1 + reason: Terraform provides a declarative module. +- technology: ansible + component: bucket + hosting: + - minio.server + - '*' + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. +- technology: terraform + component: bucket + hosting: + - minio.server + - '*' + - remote.machine + weight: 1 + reason: Terraform provides a declarative module. +- technology: ansible + component: bucket + hosting: + - minio.server + - kubernetes.cluster + weight: 1 + reason: Primary use case due to the specialization of Ansible. +- technology: terraform + component: bucket + hosting: + - minio.server + - kubernetes.cluster + weight: 1 + reason: Terraform provides a declarative module. +- technology: ansible + component: docker.engine + hosting: + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks' +- technology: terraform + component: docker.engine + hosting: + - local.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"local-exec" provider' +- technology: ansible + component: docker.engine + hosting: + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks' +- technology: terraform + component: docker.engine + hosting: + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"remote-exec" provider' +- technology: ansible + component: gcp.service + hosting: [] + weight: 1 + reason: Ansible provides a declarative module + details: '"google.cloud.gcp_serviceusage_service" task' +- technology: terraform + component: gcp.service + hosting: [] + weight: 1 + reason: Terraform provides a declarative module. + details: '"google_project_service" resource' +- technology: ansible + component: ingress + hosting: + - kubernetes.cluster + weight: 0.5 + reason: Kubernetes is more specialized. + details: '"kubernetes.core.k8s" task' +- technology: kubernetes + component: ingress + hosting: + - kubernetes.cluster + weight: 1 + reason: Kubernetes is the underlying technology. + details: Kubernetes manifest generated and applied +- technology: terraform + component: ingress + hosting: + - kubernetes.cluster + weight: 0.5 + reason: Kubernetes is more specialized. + details: '"kubernetes_service_v1" resource' +- technology: ansible + component: ingress + hosting: + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", "ansible.builtin.copy", and "ansible.builtin.systemd" tasks' +- technology: terraform + component: ingress + hosting: + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' +- technology: ansible + component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. +- technology: compose + component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - local.machine + weight: 0 + reason: One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. +- technology: terraform + component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - local.machine + weight: 0.5 + reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. +- technology: ansible + component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. +- technology: compose + component: mysql.database + 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. +- technology: terraform + component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - remote.machine + weight: 0.5 + reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. +- technology: ansible + component: mysql.database + hosting: + - mysql.dbms + - gcp.cloudsql + weight: 0.5 + reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. +- technology: terraform + component: mysql.database + hosting: + - mysql.dbms + - gcp.cloudsql + weight: 1 + reason: Terraform provides a declarative module. +- technology: ansible + component: mysql.database + hosting: + - mysql.dbms + - kubernetes.cluster + weight: 1 + reason: Primary use case due to the specialization of Ansible. +- technology: kubernetes + component: mysql.database + hosting: + - mysql.dbms + - kubernetes.cluster + weight: 0 + reason: Kubernetes Job with imperative parts, while declarative other technologies provide declarative modules. +- technology: terraform + component: mysql.database + hosting: + - mysql.dbms + - kubernetes.cluster + weight: 0 + reason: Ansible is more specialized. +- technology: ansible + component: mysql.database + hosting: + - mysql.dbms + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. +- technology: terraform + component: mysql.database + hosting: + - mysql.dbms + - remote.machine + weight: 0.5 + reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. +- technology: ansible + component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized + details: '"community.docker.docker_container" task' +- technology: compose + component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - local.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker-compose manifest generated and applied +- technology: terraform + component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' +- technology: ansible + component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized + details: '"community.docker.docker_container" task' +- technology: compose + component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - remote.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker-compose manifest generated and applied +- technology: terraform + component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' +- technology: ansible + component: mysql.dbms + artifact: dbms.image + hosting: + - gcp.cloudsql + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"google.cloud.gcp_sql_instance" and "google.cloud.gcp_sql_user" tasks' +- technology: terraform + component: mysql.dbms + artifact: dbms.image + hosting: + - gcp.cloudsql + weight: 1 + reason: Terraform provides a declarative module. + details: '"google_sql_database_instance" and "google_sql_user" resources' +- technology: ansible + component: mysql.dbms + artifact: dbms.image + hosting: + - kubernetes.cluster + weight: 0.5 + reason: Kubernetes is more specialized. + details: '"kubernetes.core.k8s" tasks' +- technology: kubernetes + component: mysql.dbms + artifact: dbms.image + hosting: + - kubernetes.cluster + weight: 1 + reason: Kubernetes is the underlying technology. + details: Kubernetes manifest generated and applied +- technology: terraform + component: mysql.dbms + artifact: dbms.image + hosting: + - kubernetes.cluster + weight: 0.5 + reason: Kubernetes is more specialized. + details: '"kubernetes_deployment_v1" and "kubernetes_service_v1" resources' +- technology: ansible + component: mysql.dbms + artifact: dbms.image + hosting: + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks' +- technology: terraform + component: mysql.dbms + artifact: dbms.image + hosting: + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' +- technology: ansible + component: bucket + artifact: cache.image + hosting: + - gcp.memorystore + weight: 0.5 + reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. +- technology: terraform + component: redis.server + artifact: cache.image + hosting: + - gcp.memorystore + weight: 1 + reason: Terraform provides a declarative module. +- technology: ansible + component: redis.server + artifact: cache.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"community.docker.docker_container" task' +- technology: compose + component: redis.server + artifact: cache.image + hosting: + - docker.engine + - local.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker compose manifest generated and applied +- technology: terraform + component: redis.server + artifact: cache.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' +- technology: ansible + component: redis.server + artifact: cache.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"community.docker.docker_container" task' +- technology: compose + component: redis.server + artifact: cache.image + hosting: + - docker.engine + - remote.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker compose manifest generated and applied +- technology: terraform + component: redis.server + artifact: cache.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' +- technology: ansible + component: redis.server + artifact: cache.image + hosting: + - kubernetes.cluster + weight: 1 + reason: Primary use case due to the specialization of Ansible. +- technology: terraform + component: redis.server + artifact: cache.image + hosting: + - kubernetes.cluster + weight: 1 + reason: Terraform provides a declarative module. +- technology: ansible + component: service.application + artifact: docker.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"community.docker.docker_container" task' +- technology: compose + component: service.application + artifact: docker.image + hosting: + - docker.engine + - local.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker compose manifest generated and applied +- technology: terraform + component: service.application + artifact: docker.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' +- technology: ansible + component: service.application + artifact: docker.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"community.docker.docker_container" task' +- technology: compose + component: service.application + artifact: docker.image + hosting: + - docker.engine + - remote.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker compose manifest generated and applied +- technology: terraform + component: service.application + artifact: docker.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' +- technology: ansible + component: service.application + artifact: docker.image + hosting: + - gcp.cloudrun + weight: 0 + reason: Custom module with imperative parts, while Terraform provides a declarative module. + details: '"ansible.builtin.shell", "ansible.builtin.tempfile", and "ansible.builtin.copy" tasks ' +- technology: terraform + component: service.application + artifact: docker.image + hosting: + - gcp.cloudrun + weight: 1 + reason: Terraform provides a declarative module. + details: '"google_cloud_run_v2_service" and "google_cloud_run_service_iam_binding" resources' +- technology: ansible + component: service.application + artifact: docker.image + hosting: + - kubernetes.cluster + weight: 0.5 + reason: Kubernetes is more specialized. + details: '"kubernetes.core.k8s" tasks' +- technology: kubernetes + component: service.application + artifact: docker.image + hosting: + - kubernetes.cluster + weight: 1 + reason: Kubernetes is the underlying technology. + details: Kubernetes manifest generated and applied +- technology: terraform + component: service.application + artifact: docker.image + hosting: + - kubernetes.cluster + weight: 0.5 + reason: Kubernetes is more specialized. + details: '"kubernetes_deployment_v1" and "kubernetes_service_v1" resources' +- technology: ansible + component: service.application + artifact: tar.archive + hosting: + - '*' + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. Special integration for systemd. + details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements' +- technology: terraform + component: service.application + artifact: tar.archive + hosting: + - '*' + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' +- technology: ansible + component: service.application + artifact: zip.archive + hosting: + - '*' + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. Special integration for systemd. + details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements' +- technology: terraform + component: service.application + artifact: zip.archive + hosting: + - '*' + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' +- technology: ansible + component: service.application + artifact: zip.archive + hosting: + - gcp.appengine + weight: 0 + reason: Custom module with imperative parts, while Terraform provides a declarative module. + details: '"ansible.builtin.shell", "ansible.builtin.tempfile", "ansible.builtin.unarchive", and "ansible.builtin.copy" tasks' +- technology: terraform + component: service.application + artifact: zip.archive + hosting: + - gcp.appengine + weight: 1 + reason: Terraform provides a declarative module. + details: '"google_app_engine_standard_app_version", "google_project_iam_member", "google_service_account", "google_storage_bucket", and "google_storage_bucket_object" resources' +- technology: ansible + component: software.application + artifact: apt.package + hosting: + - '*' + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements' +- technology: terraform + component: software.application + artifact: apt.archive + hosting: + - '*' + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"file" provisioner to upload scripts and "remote-exec" to execute scripts' +- technology: ansible + component: software.application + artifact: tar.archive + hosting: + - '*' + - remote.machine + weight: 0.5 + reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application". + details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' +- technology: terraform + component: software.application + artifact: tar.archive + hosting: + - '*' + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' +- technology: ansible + component: software.application + artifact: zip.archive + hosting: + - '*' + - remote.machine + weight: 0.5 + reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. + details: '"ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' +- technology: terraform + component: software.application + artifact: zip.archive + hosting: + - '*' + - remote.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' +- technology: ansible + component: virtual.machine + artifact: machine.image + hosting: + - openstack.provider + weight: 0.5 + reason: Terraform is more specialized. + details: '"openstack.cloud.security_group", "openstack.cloud.security_group_rule" and "openstack.cloud.server" tasks' +- technology: terraform + component: virtual.machine + artifact: machine.image + hosting: + - openstack.provider + weight: 1 + reason: Terraform provides a declarative module. + details: '"openstack_compute_instance_v2", "openstack_networking_secgroup_rule_v2" and "openstack_networking_secgroup_v2" resources' diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml deleted file mode 100644 index 971f770e97..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/rules.yaml +++ /dev/null @@ -1,568 +0,0 @@ -################################################### -# -# WARNING: Do not edit! This file is autogenerated! -# -################################################### - -ansible: - - component: bucket - hosting: - - gcp.cloudstorage - weight: 0.5 - reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. - - component: bucket - hosting: - - minio.server - - '*' - - local.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: bucket - hosting: - - minio.server - - '*' - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: bucket - hosting: - - minio.server - - kubernetes.cluster - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: docker.engine - hosting: - - local.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - details: '"ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks' - - component: docker.engine - hosting: - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - details: '"ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks' - - component: gcp.service - hosting: [] - weight: 1 - reason: Ansible provides a declarative module - details: '"google.cloud.gcp_serviceusage_service" task' - - component: ingress - hosting: - - kubernetes.cluster - weight: 0.5 - reason: Kubernetes is more specialized. - details: '"kubernetes.core.k8s" task' - - component: ingress - hosting: - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - details: '"ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", "ansible.builtin.copy", and "ansible.builtin.systemd" tasks' - - component: mysql.database - hosting: - - mysql.dbms - - docker.engine - - local.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: mysql.database - hosting: - - mysql.dbms - - docker.engine - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: mysql.database - hosting: - - mysql.dbms - - gcp.cloudsql - weight: 0.5 - reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. - - component: mysql.database - hosting: - - mysql.dbms - - kubernetes.cluster - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: mysql.database - hosting: - - mysql.dbms - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: mysql.dbms - artifact: dbms.image - hosting: - - docker.engine - - local.machine - weight: 0.5 - reason: Docker Compose is more specialized - details: '"community.docker.docker_container" task' - - component: mysql.dbms - artifact: dbms.image - hosting: - - docker.engine - - remote.machine - weight: 0.5 - reason: Docker Compose is more specialized - details: '"community.docker.docker_container" task' - - component: mysql.dbms - artifact: dbms.image - hosting: - - gcp.cloudsql - weight: 1 - reason: Primary use case due to the specialization of Ansible. - details: '"google.cloud.gcp_sql_instance" and "google.cloud.gcp_sql_user" tasks' - - component: mysql.dbms - artifact: dbms.image - hosting: - - kubernetes.cluster - weight: 0.5 - reason: Kubernetes is more specialized. - details: '"kubernetes.core.k8s" tasks' - - component: mysql.dbms - artifact: dbms.image - hosting: - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - details: '"ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks' - - component: bucket - artifact: cache.image - hosting: - - gcp.memorystore - weight: 0.5 - reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. - - component: redis.server - artifact: cache.image - hosting: - - docker.engine - - local.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"community.docker.docker_container" task' - - component: redis.server - artifact: cache.image - hosting: - - docker.engine - - remote.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"community.docker.docker_container" task' - - component: redis.server - artifact: cache.image - hosting: - - kubernetes.cluster - weight: 1 - reason: Primary use case due to the specialization of Ansible. - - component: service.application - artifact: docker.image - hosting: - - docker.engine - - local.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"community.docker.docker_container" task' - - component: service.application - artifact: docker.image - hosting: - - docker.engine - - remote.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"community.docker.docker_container" task' - - component: service.application - artifact: docker.image - hosting: - - gcp.cloudrun - weight: 0 - reason: Custom module with imperative parts, while Terraform provides a declarative module. - details: '"ansible.builtin.shell", "ansible.builtin.tempfile", and "ansible.builtin.copy" tasks ' - - component: service.application - artifact: docker.image - hosting: - - kubernetes.cluster - weight: 0.5 - reason: Kubernetes is more specialized. - details: '"kubernetes.core.k8s" tasks' - - component: service.application - artifact: tar.archive - hosting: - - '*' - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. Special integration for systemd. - details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements' - - component: service.application - artifact: zip.archive - hosting: - - '*' - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. Special integration for systemd. - details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements' - - component: service.application - artifact: zip.archive - hosting: - - gcp.appengine - weight: 0 - reason: Custom module with imperative parts, while Terraform provides a declarative module. - details: '"ansible.builtin.shell", "ansible.builtin.tempfile", "ansible.builtin.unarchive", and "ansible.builtin.copy" tasks' - - component: software.application - artifact: apt.package - hosting: - - '*' - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - details: '"ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements' - - component: software.application - artifact: tar.archive - hosting: - - '*' - - remote.machine - weight: 0.5 - reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application". - details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' - - component: software.application - artifact: zip.archive - hosting: - - '*' - - remote.machine - weight: 0.5 - reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. - details: '"ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' - - component: virtual.machine - artifact: machine.image - hosting: - - openstack.provider - weight: 0.5 - reason: Terraform is more specialized. - details: '"openstack.cloud.security_group", "openstack.cloud.security_group_rule" and "openstack.cloud.server" tasks' -terraform: - - component: bucket - hosting: - - gcp.cloudstorage - weight: 1 - reason: Terraform provides a declarative module. - - component: bucket - hosting: - - minio.server - - '*' - - local.machine - weight: 1 - reason: Terraform provides a declarative module. - - component: bucket - hosting: - - minio.server - - '*' - - remote.machine - weight: 1 - reason: Terraform provides a declarative module. - - component: bucket - hosting: - - minio.server - - kubernetes.cluster - weight: 1 - reason: Terraform provides a declarative module. - - component: docker.engine - hosting: - - local.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"local-exec" provider' - - component: docker.engine - hosting: - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"remote-exec" provider' - - component: gcp.service - hosting: [] - weight: 1 - reason: Terraform provides a declarative module. - details: '"google_project_service" resource' - - component: ingress - hosting: - - kubernetes.cluster - weight: 0.5 - reason: Kubernetes is more specialized. - details: '"kubernetes_service_v1" resource' - - component: ingress - hosting: - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' - - component: mysql.database - hosting: - - mysql.dbms - - docker.engine - - local.machine - weight: 0.5 - reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. - - component: mysql.database - hosting: - - mysql.dbms - - docker.engine - - remote.machine - weight: 0.5 - reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. - - component: mysql.database - hosting: - - mysql.dbms - - gcp.cloudsql - weight: 1 - reason: Terraform provides a declarative module. - - component: mysql.database - hosting: - - mysql.dbms - - kubernetes.cluster - weight: 0 - reason: Ansible is more specialized. - - component: mysql.database - hosting: - - mysql.dbms - - remote.machine - weight: 0.5 - reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. - - component: mysql.dbms - artifact: dbms.image - hosting: - - docker.engine - - local.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"docker_container" and "docker_image" resources' - - component: mysql.dbms - artifact: dbms.image - hosting: - - docker.engine - - remote.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"docker_container" and "docker_image" resources' - - component: mysql.dbms - artifact: dbms.image - hosting: - - gcp.cloudsql - weight: 1 - reason: Terraform provides a declarative module. - details: '"google_sql_database_instance" and "google_sql_user" resources' - - component: mysql.dbms - artifact: dbms.image - hosting: - - kubernetes.cluster - weight: 0.5 - reason: Kubernetes is more specialized. - details: '"kubernetes_deployment_v1" and "kubernetes_service_v1" resources' - - component: mysql.dbms - artifact: dbms.image - hosting: - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' - - component: redis.server - artifact: cache.image - hosting: - - gcp.memorystore - weight: 1 - reason: Terraform provides a declarative module. - - component: redis.server - artifact: cache.image - hosting: - - docker.engine - - local.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"docker_container" and "docker_image" resources' - - component: redis.server - artifact: cache.image - hosting: - - docker.engine - - remote.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"docker_container" and "docker_image" resources' - - component: redis.server - artifact: cache.image - hosting: - - kubernetes.cluster - weight: 1 - reason: Terraform provides a declarative module. - - component: service.application - artifact: docker.image - hosting: - - docker.engine - - local.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"docker_container" and "docker_image" resources' - - component: service.application - artifact: docker.image - hosting: - - docker.engine - - remote.machine - weight: 0.5 - reason: Docker Compose is more specialized. - details: '"docker_container" and "docker_image" resources' - - component: service.application - artifact: docker.image - hosting: - - gcp.cloudrun - weight: 1 - reason: Terraform provides a declarative module. - details: '"google_cloud_run_v2_service" and "google_cloud_run_service_iam_binding" resources' - - component: service.application - artifact: docker.image - hosting: - - kubernetes.cluster - weight: 0.5 - reason: Kubernetes is more specialized. - details: '"kubernetes_deployment_v1" and "kubernetes_service_v1" resources' - - component: service.application - artifact: tar.archive - hosting: - - '*' - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' - - component: service.application - artifact: zip.archive - hosting: - - '*' - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' - - component: service.application - artifact: zip.archive - hosting: - - gcp.appengine - weight: 1 - reason: Terraform provides a declarative module. - details: '"google_app_engine_standard_app_version", "google_project_iam_member", "google_service_account", "google_storage_bucket", and "google_storage_bucket_object" resources' - - component: software.application - artifact: apt.archive - hosting: - - '*' - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"file" provisioner to upload scripts and "remote-exec" to execute scripts' - - component: software.application - artifact: tar.archive - hosting: - - '*' - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' - - component: software.application - artifact: zip.archive - hosting: - - '*' - - remote.machine - weight: 0 - reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' - - component: virtual.machine - artifact: machine.image - hosting: - - openstack.provider - weight: 1 - reason: Terraform provides a declarative module. - details: '"openstack_compute_instance_v2", "openstack_networking_secgroup_rule_v2" and "openstack_networking_secgroup_v2" resources' -kubernetes: - - component: ingress - hosting: - - kubernetes.cluster - weight: 1 - reason: Kubernetes is the underlying technology. - details: Kubernetes manifest generated and applied - - component: mysql.database - hosting: - - mysql.dbms - - kubernetes.cluster - weight: 0 - reason: Kubernetes Job with imperative parts, while declarative other technologies provide declarative modules. - - component: mysql.dbms - artifact: dbms.image - hosting: - - kubernetes.cluster - weight: 1 - reason: Kubernetes is the underlying technology. - details: Kubernetes manifest generated and applied - - component: service.application - artifact: docker.image - hosting: - - kubernetes.cluster - weight: 1 - reason: Kubernetes is the underlying technology. - details: Kubernetes manifest generated and applied -compose: - - component: mysql.database - hosting: - - mysql.dbms - - docker.engine - - local.machine - weight: 0 - reason: One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. - - component: mysql.database - 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. - - component: mysql.dbms - artifact: dbms.image - hosting: - - docker.engine - - local.machine - weight: 1 - reason: Docker is the underlying technology. - details: docker-compose manifest generated and applied - - component: mysql.dbms - artifact: dbms.image - hosting: - - docker.engine - - remote.machine - weight: 1 - reason: Docker is the underlying technology. - details: docker-compose manifest generated and applied - - component: redis.server - artifact: cache.image - hosting: - - docker.engine - - local.machine - weight: 1 - reason: Docker is the underlying technology. - details: docker compose manifest generated and applied - - component: redis.server - artifact: cache.image - hosting: - - docker.engine - - remote.machine - weight: 1 - reason: Docker is the underlying technology. - details: docker compose manifest generated and applied - - component: service.application - artifact: docker.image - hosting: - - docker.engine - - local.machine - weight: 1 - reason: Docker is the underlying technology. - details: docker compose manifest generated and applied - - component: service.application - artifact: docker.image - hosting: - - docker.engine - - remote.machine - weight: 1 - reason: Docker is the underlying technology. - details: docker compose manifest generated and applied diff --git a/tasks/docs/generate/rules/task.ts b/tasks/docs/generate/rules/task.ts index 6681b5f1bb..e0408605d2 100644 --- a/tasks/docs/generate/rules/task.ts +++ b/tasks/docs/generate/rules/task.ts @@ -52,7 +52,7 @@ async function main() { for (const [index, rule] of rules.entries()) { assert.isDefined(rule.weight) assert.isDefined(rule.reason) - assert.isDefined(rule.details) + //assert.isDefined(rule.details) assert.isDefined(rule.hosting) const description = descriptions.find(it => it.id === rule.technology) @@ -64,7 +64,7 @@ async function main() { name: description.name, quality: rule.weight, reason: rule.reason, - details: rule.details, + details: rule.details!, } const found = scenarios.find(it => it.key === key) diff --git a/tasks/docs/generate/rules/template.ejs b/tasks/docs/generate/rules/template.ejs index 93f6b09b7b..ccec3b09f5 100644 --- a/tasks/docs/generate/rules/template.ejs +++ b/tasks/docs/generate/rules/template.ejs @@ -81,19 +81,11 @@ The scenario does not require a specific hosting. This appendix contains the deployment technology rules. -<% -let count = 0 -Object.entries(data).forEach(([technology, rules]) => { - const description = descriptions.find(it => it.id === technology) --%> - -<% rules.forEach((rule, index) => { - count++ --%> -### Rule #<%= count %> +<% data.forEach((rule, index) => { -%> +### Rule #<%= index + 1 %> | Attribute | Value | | --- | --- | -| Identifier | <%= constructRuleName({technology, ...rule}) %> | +| Identifier | <%= constructRuleName(rule) %> | | Component | <%= link(rule.component) %> | <% if (rule.artifact) {-%> | Artifact | <%= link(rule.artifact) %> | @@ -104,10 +96,9 @@ Object.entries(data).forEach(([technology, rules]) => { | Quality | <%= rule.weight %> | | Reason | <%= rule.reason %> | | Details | <%= rule.details %> | -| Graph |
<%- svgs["rule." + technology + "." + (index + 1)]%>
| +| Graph |
<%- svgs["rule." + rule.technology + "." + (index + 1)]%>
| <% }) %> -<% }) %> ## Appendix B "YAML" From 855691e3acda308b8e347f5fe84c522f2e708ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Sat, 7 Sep 2024 22:49:39 +0200 Subject: [PATCH 06/18] technology refactoring --- src/technologies/plugins/rules/.template.ts | 2 +- .../bucket/gcp-cloudstorage/ansible/index.ts | 8 +- .../gcp-cloudstorage/terraform/index.ts | 8 +- .../asterisk/local-machine/ansible/index.ts | 8 +- .../asterisk/local-machine/terraform/index.ts | 8 +- .../asterisk/remote-machine/ansible/index.ts | 8 +- .../remote-machine/terraform/index.ts | 8 +- .../minio/kubernetes-cluster/ansible/index.ts | 8 +- .../kubernetes-cluster/terraform/index.ts | 8 +- .../local-machine/ansible/index.ts | 118 +----- .../local-machine/terraform/index.ts | 90 +---- .../remote-machine/ansible/index.ts | 105 +----- .../remote-machine/terraform/index.ts | 92 ++--- .../rules/generators/docker-engine/utils.ts | 126 +++++++ .../generators/gcp-service/ansible/index.ts | 13 +- .../generators/gcp-service/terraform/index.ts | 19 +- .../kubernetes-cluster/ansible/index.ts | 6 +- .../kubernetes-cluster/kubernetes/index.ts | 4 +- .../kubernetes-cluster/terraform/index.ts | 19 +- .../ingress/remote-machine/ansible/index.ts | 6 +- .../ingress/remote-machine/terraform/index.ts | 9 +- .../local-machine/ansible/index.ts | 3 +- .../local-machine/compose/index.ts | 148 ++++---- .../local-machine/terraform/index.ts | 4 +- .../remote-machine/ansible/index.ts | 111 +++--- .../remote-machine/compose/index.ts | 20 +- .../remote-machine/terraform/index.ts | 4 +- .../mysql-dbms/gcp-cloudsql/ansible/index.ts | 8 +- .../gcp-cloudsql/terraform/index.ts | 8 +- .../kubernetes-cluster/ansible/index.ts | 4 +- .../kubernetes-cluster/kubernetes/index.ts | 4 +- .../kubernetes-cluster/terraform/index.ts | 4 +- .../remote-machine/ansible/index.ts | 10 +- .../remote-machine/terraform/index.ts | 4 +- .../local-machine/ansible/index.ts | 35 +- .../local-machine/compose/index.ts | 74 ++-- .../local-machine/terraform/index.ts | 15 +- .../remote-machine/ansible/index.ts | 38 +- .../remote-machine/compose/index.ts | 67 ++-- .../remote-machine/terraform/index.ts | 32 +- .../gcp-cloudsql/ansible/index.ts | 8 +- .../gcp-cloudsql/terraform/index.ts | 8 +- .../kubernetes-cluster/ansible/index.ts | 6 +- .../kubernetes-cluster/kubernetes/index.ts | 4 +- .../kubernetes-cluster/terraform/index.ts | 8 +- .../remote-machine/ansible/index.ts | 6 +- .../remote-machine/terraform/index.ts | 11 +- .../local-machine/ansible/index.ts | 36 +- .../local-machine/compose/index.ts | 72 ++-- .../local-machine/terraform/index.ts | 10 +- .../remote-machine/ansible/index.ts | 35 +- .../remote-machine/compose/index.ts | 22 +- .../remote-machine/terraform/index.ts | 8 +- .../gcp-memorystore/ansible/index.ts | 8 +- .../gcp-memorystore/terraform/index.ts | 8 +- .../kubernetes-cluster/ansible/index.ts | 8 +- .../kubernetes-cluster/terraform/index.ts | 8 +- .../local-machine/ansible/index.ts | 36 +- .../local-machine/compose/index.ts | 73 ++-- .../local-machine/terraform/index.ts | 17 +- .../remote-machine/ansible/index.ts | 38 +- .../remote-machine/compose/index.ts | 72 ++-- .../remote-machine/terraform/index.ts | 8 +- .../gcp-cloudrun/ansible/index.ts | 10 +- .../gcp-cloudrun/terraform/index.ts | 10 +- .../kubernetes-cluster/ansible/index.ts | 8 +- .../kubernetes-cluster/kubernetes/index.ts | 8 +- .../kubernetes-cluster/terraform/index.ts | 8 +- .../asterisk/remote-machine/ansible/index.ts | 26 +- .../remote-machine/terraform/index.ts | 31 +- .../asterisk/remote-machine/ansible/index.ts | 26 +- .../remote-machine/terraform/index.ts | 31 +- .../gcp-appengine/ansible/index.ts | 11 +- .../gcp-appengine/terraform/index.ts | 17 +- .../asterisk/remote-machine/ansible/index.ts | 28 +- .../remote-machine/terraform/index.ts | 33 +- .../asterisk/remote-machine/ansible/index.ts | 28 +- .../remote-machine/terraform/index.ts | 39 +- .../asterisk/remote-machine/ansible/index.ts | 28 +- .../remote-machine/terraform/index.ts | 39 +- .../openstack-provider/ansible/index.ts | 4 +- .../openstack-provider/terraform/index.ts | 6 +- .../plugins/rules/utils/ansible.ts | 339 ++++++++++++++++++ .../plugins/rules/utils/compose.ts | 12 + .../plugins/rules/utils/kubernetes.ts | 11 + .../plugins/rules/utils/terraform.ts | 104 ++++++ .../plugins/rules/{ => utils}/utils.ts | 259 ++----------- 87 files changed, 1414 insertions(+), 1478 deletions(-) create mode 100644 src/technologies/plugins/rules/generators/docker-engine/utils.ts create mode 100644 src/technologies/plugins/rules/utils/ansible.ts create mode 100644 src/technologies/plugins/rules/utils/compose.ts create mode 100644 src/technologies/plugins/rules/utils/kubernetes.ts create mode 100644 src/technologies/plugins/rules/utils/terraform.ts rename src/technologies/plugins/rules/{ => utils}/utils.ts (55%) diff --git a/src/technologies/plugins/rules/.template.ts b/src/technologies/plugins/rules/.template.ts index 6bbabaaf22..95ff20d7f3 100644 --- a/src/technologies/plugins/rules/.template.ts +++ b/src/technologies/plugins/rules/.template.ts @@ -1,5 +1,5 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import {MetadataGenerated} from '#technologies/plugins/rules/utils' +import {MetadataGenerated} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { reason: '', diff --git a/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts b/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts index 4688a24cf8..4bd0dc9b39 100644 --- a/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - AnsibleOrchestratorOperation, - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this, see https://docs.ansible.com/ansible/latest/collections/google/cloud/gcp_storage_object_module.html diff --git a/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/terraform/index.ts b/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/terraform/index.ts index 9822275c38..1810a7829f 100644 --- a/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/terraform/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this, see https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket diff --git a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/ansible/index.ts index ab92c9c51f..31e2bc62d6 100644 --- a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/ansible/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - AnsibleOrchestratorOperation, - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this diff --git a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/terraform/index.ts index ca6a75cfee..e221a48156 100644 --- a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/terraform/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this, see https://registry.terraform.io/providers/aminueza/minio/latest diff --git a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/ansible/index.ts index f74ec3e987..f1086537f0 100644 --- a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/ansible/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - AnsibleOrchestratorOperation, - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this diff --git a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/terraform/index.ts index f5ee64fb68..712a461241 100644 --- a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/terraform/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this, see https://registry.terraform.io/providers/aminueza/minio/latest diff --git a/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/ansible/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/ansible/index.ts index 5267ebc040..4f0976e980 100644 --- a/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/ansible/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - AnsibleOrchestratorOperation, - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this diff --git a/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/terraform/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/terraform/index.ts index 1cf64ed9fc..36d7224210 100644 --- a/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/terraform/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this, see https://registry.terraform.io/providers/aminueza/minio/latest diff --git a/src/technologies/plugins/rules/generators/docker-engine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/docker-engine/local-machine/ansible/index.ts index 4cd57709f8..f871222bb0 100644 --- a/src/technologies/plugins/rules/generators/docker-engine/local-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/docker-engine/local-machine/ansible/index.ts @@ -1,13 +1,10 @@ -import * as files from '#files' -import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { - AnsibleOrchestratorOperation, - AnsibleWaitForSSHTask, - MetadataGenerated, - MetadataUnfurl, -} from '#technologies/plugins/rules/utils' - -// TODO: maybe dont install but only check if installed? + AnsibleDockerEngineInstallationTasks, + AnsibleDockerEngineUninstallationTasks, +} from '#technologies/plugins/rules/generators/docker-engine/utils' +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {LOCALHOST, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'docker.engine', @@ -18,36 +15,6 @@ 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: { @@ -57,7 +24,7 @@ const generator: ImplementationGenerator = { attributes: { application_address: { type: 'string', - default: '127.0.0.1', + default: LOCALHOST, }, }, interfaces: { @@ -69,48 +36,7 @@ const generator: ImplementationGenerator = { }, inputs: { playbook: { - q: [ - { - ...AnsibleWaitForSSHTask(), - }, - { - name: 'install docker', - '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: service, - }, - }, - { - 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', - }, - }, - { - name: 'add user to docker group', - 'ansible.builtin.user': { - name: '{{ SELF.os_ssh_user }}', - groups: 'docker', - append: 'yes', - }, - }, - ], + q: [...AnsibleDockerEngineInstallationTasks()], }, }, }, @@ -120,33 +46,7 @@ const generator: ImplementationGenerator = { }, inputs: { playbook: { - q: [ - // 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'], - }, - ], + q: [...AnsibleDockerEngineUninstallationTasks()], }, }, }, diff --git a/src/technologies/plugins/rules/generators/docker-engine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/docker-engine/local-machine/terraform/index.ts index 8ddf9fbe77..f0a987889b 100644 --- a/src/technologies/plugins/rules/generators/docker-engine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/docker-engine/local-machine/terraform/index.ts @@ -1,56 +1,15 @@ +import { + DockerEngineServiceUnit, + TerraformDockerEngineInstallationTasks, + TerraformDockerEngineUninstallationTasks, +} from '#technologies/plugins/rules/generators/docker-engine/utils' import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import {MetadataGenerated, MetadataUnfurl, TerraformStandardOperations} from '#technologies/plugins/rules/utils' -import * as utils from '#utils' - -// TODO: maybe dont install but only check if installed? -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 -`) +import { + TerraformLocalProviderImport, + TerraformRequiredVersion, + TerraformStandardOperations, +} from '#technologies/plugins/rules/utils/terraform' +import {LOCALHOST, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'docker.engine', @@ -70,7 +29,7 @@ const generator: ImplementationGenerator = { attributes: { application_address: { type: 'string', - default: '127.0.0.1', + default: LOCALHOST, }, }, interfaces: { @@ -83,17 +42,17 @@ const generator: ImplementationGenerator = { required_providers: [ { mysql: { - source: 'hashicorp/local', - version: '2.5.1', + ...TerraformLocalProviderImport(), }, }, ], + ...TerraformRequiredVersion(), }, ], provider: { local: [ { - endpoint: '127.0.0.1:{{ HOST.management_port }}', + endpoint: `${LOCALHOST}:{{ HOST.management_port }}`, password: '{{ HOST.dbms_password }}', username: 'root', }, @@ -102,7 +61,7 @@ const generator: ImplementationGenerator = { resource: { local_file: { tmp_service: { - content: service, + content: DockerEngineServiceUnit(), filename: '/tmp/docker.service', }, }, @@ -113,23 +72,10 @@ const generator: ImplementationGenerator = { provisioner: { 'local-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: [...TerraformDockerEngineInstallationTasks()], }, - // 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', - ], + inline: [...TerraformDockerEngineUninstallationTasks()], when: 'destroy', }, ], 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 dc2f9813f5..e7ecfd9324 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,13 +1,14 @@ -import * as files from '#files' +import { + AnsibleDockerEngineInstallationTasks, + AnsibleDockerEngineUninstallationTasks, +} from '#technologies/plugins/rules/generators/docker-engine/utils' import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, AnsibleWaitForSSHTask, - MetadataGenerated, - MetadataUnfurl, - OpenstackMachineCredentials, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/ansible' +import {MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'docker.engine', @@ -18,36 +19,6 @@ 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: { @@ -68,43 +39,7 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, - { - name: 'install docker', - '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: service, - }, - }, - { - 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', - }, - }, - { - name: 'add user to docker group', - 'ansible.builtin.user': { - name: '{{ SELF.os_ssh_user }}', - groups: 'docker', - append: 'yes', - }, - }, + ...AnsibleDockerEngineInstallationTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -120,31 +55,7 @@ const generator: ImplementationGenerator = { { ...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'], - }, + ...AnsibleDockerEngineUninstallationTasks(), ], }, 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 86fb3f0150..9843192464 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 @@ -1,61 +1,20 @@ +import { + DockerEngineServiceUnit, + TerraformDockerEngineInstallationTasks, + TerraformDockerEngineUninstallationTasks, +} from '#technologies/plugins/rules/generators/docker-engine/utils' import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + TerraformRequiredVersion, + TerraformSSHConnection, + TerraformStandardOperations, +} from '#technologies/plugins/rules/utils/terraform' import { MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, 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 -`) +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'docker.engine', @@ -88,44 +47,33 @@ const generator: ImplementationGenerator = { defaults: { inputs: { main: { + terraform: [ + { + ...TerraformRequiredVersion(), + }, + ], resource: { terraform_data: { docker: [ { connection: [ { - host: '{{ SELF.os_ssh_host }}', - private_key: '${file("{{ SELF.os_ssh_key_file }}")}', - type: 'ssh', - user: '{{ SELF.os_ssh_user }}', + ...TerraformSSHConnection(), }, ], provisioner: { file: [ { - content: service, + content: DockerEngineServiceUnit(), 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: [...TerraformDockerEngineInstallationTasks()], }, - // 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', - ], + inline: [...TerraformDockerEngineUninstallationTasks()], when: 'destroy', }, ], diff --git a/src/technologies/plugins/rules/generators/docker-engine/utils.ts b/src/technologies/plugins/rules/generators/docker-engine/utils.ts new file mode 100644 index 0000000000..0363cc9d01 --- /dev/null +++ b/src/technologies/plugins/rules/generators/docker-engine/utils.ts @@ -0,0 +1,126 @@ +import * as files from '#files' + +export function DockerEngineServiceUnit() { + return 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', + }, + }) +} + +export function AnsibleDockerEngineInstallationTasks() { + return [ + { + name: 'install docker', + '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: DockerEngineServiceUnit(), + }, + }, + { + 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', + }, + }, + { + name: 'add user to docker group', + 'ansible.builtin.user': { + name: '{{ SELF.os_ssh_user }}', + groups: 'docker', + append: 'yes', + }, + }, + ] +} + +/** + * https://docs.docker.com/engine/install/ubuntu/#uninstall-docker-engine + */ +export function AnsibleDockerEngineUninstallationTasks() { + return [ + { + 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'], + }, + ] +} + +export function TerraformDockerEngineInstallationTasks() { + return [ + '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', + ] +} + +export function TerraformDockerEngineUninstallationTasks() { + return [ + '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', + ] +} 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 27b3f29386..3d6db75534 100644 --- a/src/technologies/plugins/rules/generators/gcp-service/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/gcp-service/ansible/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - AnsibleOrchestratorOperation, - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +import {AnsibleGCPCredentialsEnvironment, AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'gcp.service', @@ -31,10 +27,7 @@ const generator: ImplementationGenerator = { implementation: { ...AnsibleOrchestratorOperation(), environment: { - GCP_SERVICE_ACCOUNT_FILE: { - eval: '.::gcp_service_account_file', - }, - GCP_AUTH_KIND: 'serviceaccount', + ...AnsibleGCPCredentialsEnvironment(), }, }, inputs: { diff --git a/src/technologies/plugins/rules/generators/gcp-service/terraform/index.ts b/src/technologies/plugins/rules/generators/gcp-service/terraform/index.ts index f35fd103eb..24d1940460 100644 --- a/src/technologies/plugins/rules/generators/gcp-service/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/gcp-service/terraform/index.ts @@ -1,10 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, + TerraformGoogleProviderConfiguration, + TerraformGoogleProviderImport, + TerraformRequiredVersion, TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/terraform' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'gcp.service', @@ -33,20 +34,16 @@ const generator: ImplementationGenerator = { { required_providers: [ { - google: { - source: 'hashicorp/google', - version: '4.67.0', - }, + google: {...TerraformGoogleProviderImport()}, }, ], + ...TerraformRequiredVersion(), }, ], provider: { google: [ { - credentials: '{{ SELF.gcp_service_account_file }}', - project: '{{ SELF.gcp_project }}', - region: '{{ SELF.gcp_region }}', + ...TerraformGoogleProviderConfiguration(), }, ], }, 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 8f7b352ca5..2856bc2263 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 @@ -2,10 +2,8 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleKubernetesCredentialsEnvironment, AnsibleOrchestratorOperation, - KubernetesCredentials, - MetadataGenerated, - MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/ansible' +import {KubernetesCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'ingress', 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 f63bdcef0f..13c0055bc7 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,11 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' import { - AnsibleOrchestratorOperation, BASH_KUBECTL, KubernetesCredentials, MetadataGenerated, MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'ingress', diff --git a/src/technologies/plugins/rules/generators/ingress/kubernetes-cluster/terraform/index.ts b/src/technologies/plugins/rules/generators/ingress/kubernetes-cluster/terraform/index.ts index 4ab2d7e7c7..a6bf0c82a9 100644 --- a/src/technologies/plugins/rules/generators/ingress/kubernetes-cluster/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/ingress/kubernetes-cluster/terraform/index.ts @@ -1,10 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { - KubernetesCredentials, - MetadataGenerated, - MetadataUnfurl, + TerraformKubernetesProviderConfiguration, + TerraformKubernetesProviderImport, + TerraformRequiredVersion, TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/terraform' +import {KubernetesCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'ingress', @@ -39,21 +40,17 @@ const generator: ImplementationGenerator = { required_providers: [ { kubernetes: { - source: 'hashicorp/kubernetes', - version: '2.31.0', + ...TerraformKubernetesProviderImport(), }, }, ], - required_version: '>= 0.14.0', + ...TerraformRequiredVersion(), }, ], provider: { kubernetes: [ { - client_certificate: '${file("{{ SELF.k8s_client_cert_file }}")}', - client_key: '${file("{{ SELF.k8s_client_key_file }}")}', - cluster_ca_certificate: '${file("{{ SELF.k8s_ca_cert_file }}")}', - host: '{{ SELF.k8s_host }}', + ...TerraformKubernetesProviderConfiguration(), }, ], }, 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 9b6866dc3d..f8b01ba0ea 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 @@ -3,10 +3,8 @@ import { AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, AnsibleWaitForSSHTask, - MetadataGenerated, - MetadataUnfurl, - OpenstackMachineCredentials, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/ansible' +import {MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'ingress', diff --git a/src/technologies/plugins/rules/generators/ingress/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/ingress/remote-machine/terraform/index.ts index ab357213b3..85b84f44ea 100644 --- a/src/technologies/plugins/rules/generators/ingress/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/ingress/remote-machine/terraform/index.ts @@ -1,12 +1,12 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {TerraformSSHConnection, TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { BASH_HEADER, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, OpenstackMachineHost, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const script = ` ${BASH_HEADER} @@ -65,10 +65,7 @@ const generator: ImplementationGenerator = { { connection: [ { - host: '{{ SELF.os_ssh_host }}', - private_key: '${file("{{ SELF.os_ssh_key_file }}")}', - type: 'ssh', - user: '{{ SELF.os_ssh_user }}', + ...TerraformSSHConnection(), }, ], provisioner: { diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/ansible/index.ts index a092cd29b2..cf3d5b5984 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/ansible/index.ts @@ -1,5 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import {AnsibleOrchestratorOperation, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.database', diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/compose/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/compose/index.ts index 55e7a8c968..7df671b19e 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/compose/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/compose/index.ts @@ -1,5 +1,12 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import {AnsibleOrchestratorOperation, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils' +import { + AnsibleApplyComposeTask, + AnsibleCreateComposeTask, + AnsibleOrchestratorOperation, + AnsibleTouchComposeTask, + AnsibleUnapplyComposeTask, +} from '#technologies/plugins/rules/utils/ansible' +import {MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: we assume that dbms is exposed @@ -11,68 +18,61 @@ const generator: ImplementationGenerator = { 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) => { + const Operation = (query: string) => { return { - name: 'create compose', - 'ansible.builtin.copy': { - dest: '{{ compose.path }}', - content: '{{ manifest | to_yaml }}', + implementation: { + ...AnsibleOrchestratorOperation(), }, - 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, - ], + inputs: { + playbook: { + q: [ + { + ...AnsibleTouchComposeTask({ + suffix: '{{ SELF.database_name }}-{{ HOST.dbms_name }}.database', + }), }, - }, + { + ...AnsibleCreateComposeTask({ + 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, + ], + }, + }, + }, + }), + }, + { + ...AnsibleApplyComposeTask(), + }, + { + name: 'give job some time', + 'ansible.builtin.pause': { + seconds: 10, + }, + }, + { + ...AnsibleUnapplyComposeTask(), + }, + ], }, }, } } - const AnsibleApplyJobTasks = [ - { - 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', - }, - }, - ] - return { derived_from: name, metadata: { @@ -82,38 +82,12 @@ const generator: ImplementationGenerator = { 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, - ], - }, - }, - }, + create: Operation( + "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 }}'@'%';" + ), + delete: Operation( + "DROP USER IF EXISTS '{{ SELF.database_user }}'@'%'; DROP DATABASE IF EXISTS {{ SELF.database_name }};" + ), }, }, }, diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/terraform/index.ts index a2896369be..efb7ac23e4 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/terraform/index.ts @@ -1,11 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, OpenstackMachineHost, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' // TODO: we assume that dbms is exposed diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/ansible/index.ts index 23ae0c7f83..75bd0c8a87 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/ansible/index.ts @@ -1,12 +1,14 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleAptTask, + AnsibleDockerContainerTask, AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, + AnsibleMySQLDatabaseTask, + AnsibleMySQLUserTask, AnsibleWaitForSSHTask, - MetadataGenerated, - MetadataUnfurl, - OpenstackMachineCredentials, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/ansible' +import {MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials} from '#technologies/plugins/rules/utils/utils' // TODO: still need to test port forwarding, i.e., if dbms not in host @@ -61,15 +63,17 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - name: 'install pip', - apt: { - name: 'python3-pip', - state: 'present', - }, + ...AnsibleAptTask({ + name: 'install pip', + apt: { + name: 'python3-pip', + state: 'present', + }, + }), }, { name: 'install pymysql', - pip: { + 'ansible.builtin.pip': { name: 'pymysql', state: 'present', }, @@ -82,14 +86,17 @@ const generator: ImplementationGenerator = { register: 'dbms_container_info', }, { - name: 'forward port', - 'community.docker.docker_container': { - name: '{{ HOST.dbms_name }}-port-forward', - image: 'nicolaka/netshoot:v0.13', - command: 'socat TCP6-LISTEN:3306,fork TCP:{{ HOST.dbms_name }}:3306', - ports: ['{{ HOST.application_port }}:3306'], - }, - when: "'host' not in dbms_container_info.container.NetworkSettings.Networks", + ...AnsibleDockerContainerTask({ + name: 'forward port', + container: { + name: '{{ HOST.dbms_name }}-port-forward', + image: 'nicolaka/netshoot:v0.13', + command: + 'socat TCP6-LISTEN:3306,fork TCP:{{ HOST.dbms_name }}:3306', + ports: ['{{ HOST.application_port }}:3306'], + }, + when: "'host' not in dbms_container_info.container.NetworkSettings.Networks", + }), }, { name: 'create forwarding network', @@ -103,28 +110,32 @@ const generator: ImplementationGenerator = { when: "'host' not in dbms_container_info.container.NetworkSettings.Networks", }, { - name: 'create database', - 'community.mysql.mysql_db': { - name: '{{ SELF.database_name }}', - ...login, - }, + ...AnsibleMySQLDatabaseTask({ + name: 'create database', + database: { + name: '{{ SELF.database_name }}', + ...login, + }, + }), }, { - name: 'create user (with privileges)', - 'community.mysql.mysql_user': { - ...user, - ...login, - }, + ...AnsibleMySQLUserTask({ + name: 'create user (with privileges)', + user: { + ...user, + ...login, + }, + }), }, { - name: 'unforward port', - 'community.docker.docker_container': { - name: '{{ HOST.dbms_name }}-port-forward', - image: 'nicolaka/netshoot:v0.13', - network_mode: 'host', - state: 'absent', - }, - when: "'host' not in dbms_container_info.container.NetworkSettings.Networks", + ...AnsibleDockerContainerTask({ + name: 'unforward port', + container: { + name: '{{ HOST.dbms_name }}-port-forward', + state: 'absent', + }, + when: "'host' not in dbms_container_info.container.NetworkSettings.Networks", + }), }, { name: 'remove forwarding network', @@ -150,20 +161,24 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - name: 'delete user (with privileges)', - 'community.mysql.mysql_user': { - state: 'absent', - ...user, - ...login, - }, + ...AnsibleMySQLUserTask({ + name: 'delete user (with privileges)', + user: { + state: 'absent', + ...user, + ...login, + }, + }), }, { - name: 'delete database', - 'community.mysql.mysql_db': { - name: '{{ SELF.database_name }}', - state: 'absent', - ...login, - }, + ...AnsibleMySQLDatabaseTask({ + name: 'delete database', + database: { + name: '{{ SELF.database_name }}', + state: 'absent', + ...login, + }, + }), }, ], }, 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 index cbdda353bd..bcfeb3a948 100644 --- 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 @@ -1,11 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleApplyComposeTask, AnsibleDockerHostEnvironment, AnsibleOrchestratorOperation, - MetadataGenerated, - MetadataUnfurl, - OpenstackMachineHost, -} from '#technologies/plugins/rules/utils' + AnsibleUnapplyComposeTask, +} from '#technologies/plugins/rules/utils/ansible' +import {MetadataGenerated, MetadataUnfurl, OpenstackMachineHost} from '#technologies/plugins/rules/utils/utils' // TODO: we assume that dbms is exposed @@ -58,11 +58,7 @@ const generator: ImplementationGenerator = { const AnsibleApplyJobTasks = [ { - name: 'apply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', - args: { - executable: '/usr/bin/bash', - }, + ...AnsibleApplyComposeTask(), environment: { ...AnsibleDockerHostEnvironment(), }, @@ -74,11 +70,7 @@ const generator: ImplementationGenerator = { }, }, { - name: 'unapply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', - args: { - executable: '/usr/bin/bash', - }, + ...AnsibleUnapplyComposeTask(), environment: { ...AnsibleDockerHostEnvironment(), }, diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/terraform/index.ts index 02d9e84768..618a6b8922 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/remote-machine/terraform/index.ts @@ -1,11 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, OpenstackMachineHost, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' // TODO: we assume that dbms is exposed diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/gcp-cloudsql/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/gcp-cloudsql/ansible/index.ts index 14a24539a5..33d7f35218 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/gcp-cloudsql/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/gcp-cloudsql/ansible/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - AnsibleOrchestratorOperation, - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.database', diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/gcp-cloudsql/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/gcp-cloudsql/terraform/index.ts index 7fcc764605..c404b28aad 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/gcp-cloudsql/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/gcp-cloudsql/terraform/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.database', 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 090e900d91..d6eb93b9aa 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,11 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' import { - AnsibleOrchestratorOperation, BASH_KUBECTL, KubernetesCredentials, MetadataGenerated, MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.database', 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 9a88d82b01..d9c40c48f3 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,11 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' import { - AnsibleOrchestratorOperation, BASH_KUBECTL, KubernetesCredentials, MetadataGenerated, MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.database', 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 8d4e28b485..231eca8d58 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,11 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { BASH_KUBECTL, KubernetesCredentials, MetadataGenerated, MetadataUnfurl, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' /** * Official Kubernetes provider does not provide "kubectl exec", https://registry.terraform.io/providers/hashicorp/kubernetes 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 bf2a150e78..68884260b1 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 @@ -3,10 +3,8 @@ import { AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, AnsibleWaitForSSHTask, - MetadataGenerated, - MetadataUnfurl, - OpenstackMachineCredentials, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/ansible' +import {MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.database', @@ -54,14 +52,14 @@ const generator: ImplementationGenerator = { }, { name: 'install pip', - apt: { + 'ansible.builtin.apt': { name: 'python3-pip', state: 'present', }, }, { name: 'install pymysql', - pip: { + 'ansible.builtin.pip': { name: 'pymysql', state: 'present', }, diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/remote-machine/terraform/index.ts index 261dccce2c..8d2bc22026 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/remote-machine/terraform/index.ts @@ -1,11 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, OpenstackMachineHost, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.database', diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/ansible/index.ts index 1b7988fe2e..94b04ab9b7 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/ansible/index.ts @@ -1,5 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import {AnsibleOrchestratorOperation, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils' +import {AnsibleDockerContainerTask, AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {LOCALHOST, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.dbms', @@ -20,7 +21,7 @@ const generator: ImplementationGenerator = { attributes: { application_address: { type: 'string', - default: '127.0.0.1', + default: LOCALHOST, }, application_port: { type: 'string', @@ -48,15 +49,17 @@ const generator: ImplementationGenerator = { playbook: { q: [ { - name: 'start container', - 'community.docker.docker_container': { - name: '{{ SELF.dbms_name }}', - image: 'mysql:{{ ".artifacts::dbms_image::file" | eval }}', - network_mode: 'host', - env: { - MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password | string }}', + ...AnsibleDockerContainerTask({ + name: 'start container', + container: { + name: '{{ SELF.dbms_name }}', + image: 'mysql:{{ ".artifacts::dbms_image::file" | eval }}', + network_mode: 'host', + env: { + MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password | string }}', + }, }, - }, + }), }, ], }, @@ -70,11 +73,13 @@ const generator: ImplementationGenerator = { playbook: { q: [ { - name: 'delete container', - 'community.docker.docker_container': { - name: '{{ SELF.dbms_name }}', - state: 'absent', - }, + ...AnsibleDockerContainerTask({ + name: 'delete container', + container: { + name: '{{ SELF.dbms_name }}', + state: 'absent', + }, + }), }, ], }, diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/compose/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/compose/index.ts index d1e86a2c8d..e992cb71ce 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/compose/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/compose/index.ts @@ -1,10 +1,14 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleApplyComposeTask, + AnsibleCreateComposeTask, AnsibleHostEndpointCapability, AnsibleOrchestratorOperation, - MetadataGenerated, - MetadataUnfurl, -} from '#technologies/plugins/rules/utils' + AnsibleTouchComposeTask, + AnsibleUnapplyComposeTask, +} from '#technologies/plugins/rules/utils/ansible' +import {DockerCompose} from '#technologies/plugins/rules/utils/compose' +import {MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.dbms', @@ -16,32 +20,16 @@ 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 }}', - }, - }, + const suffix = '{{ SELF.dbms_name }}' + const manifest: DockerCompose = { + 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 }}', }, }, }, @@ -86,14 +74,14 @@ const generator: ImplementationGenerator = { inputs: { playbook: { q: [ - AnsibleTouchComposeTask, - AnsibleCreateComposeTask, { - name: 'apply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', - args: { - executable: '/usr/bin/bash', - }, + ...AnsibleTouchComposeTask({suffix}), + }, + { + ...AnsibleCreateComposeTask({manifest}), + }, + { + ...AnsibleApplyComposeTask(), }, { name: 'let it cook', @@ -112,14 +100,14 @@ const generator: ImplementationGenerator = { inputs: { playbook: { q: [ - AnsibleTouchComposeTask, - AnsibleCreateComposeTask, { - name: 'unapply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', - args: { - executable: '/usr/bin/bash', - }, + ...AnsibleTouchComposeTask({suffix}), + }, + { + ...AnsibleCreateComposeTask({manifest}), + }, + { + ...AnsibleUnapplyComposeTask(), }, ], }, diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/terraform/index.ts index 78fe46f70e..d3c7fadff5 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/terraform/index.ts @@ -1,12 +1,16 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleHostEndpointCapability} from '#technologies/plugins/rules/utils/ansible' +import { + TerraformDockerProviderImport, + TerraformDockerProviderLocalConfiguration, + TerraformStandardOperations, +} from '#technologies/plugins/rules/utils/terraform' import { - AnsibleHostEndpointCapability, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, OpenstackMachineHost, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.dbms', @@ -61,8 +65,7 @@ const generator: ImplementationGenerator = { required_providers: [ { docker: { - source: 'kreuzwerker/docker', - version: '3.0.2', + ...TerraformDockerProviderImport(), }, }, ], @@ -71,7 +74,7 @@ const generator: ImplementationGenerator = { provider: { docker: [ { - host: 'unix:///var/run/docker.sock', + ...TerraformDockerProviderLocalConfiguration(), }, ], }, diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/ansible/index.ts index 0a42711be3..c07c4e2cfb 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/ansible/index.ts @@ -1,12 +1,16 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleDockerContainerTask, AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, AnsibleWaitForSSHTask, +} from '#technologies/plugins/rules/utils/ansible' +import { + LOCALHOST, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.dbms', @@ -28,7 +32,7 @@ const generator: ImplementationGenerator = { attributes: { application_address: { type: 'string', - default: '127.0.0.1', + default: LOCALHOST, }, application_port: { type: 'string', @@ -59,15 +63,17 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - name: 'start container', - 'community.docker.docker_container': { - name: '{{ SELF.dbms_name }}', - image: 'mysql:{{ ".artifacts::dbms_image::file" | eval }}', - network_mode: 'host', - env: { - MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password | string }}', + ...AnsibleDockerContainerTask({ + name: 'start container', + container: { + name: '{{ SELF.dbms_name }}', + image: 'mysql:{{ ".artifacts::dbms_image::file" | eval }}', + network_mode: 'host', + env: { + MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password | string }}', + }, }, - }, + }), }, ], }, @@ -85,11 +91,13 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - name: 'delete container', - 'community.docker.docker_container': { - name: '{{ SELF.dbms_name }}', - state: 'absent', - }, + ...AnsibleDockerContainerTask({ + name: 'stop container', + container: { + name: '{{ SELF.application_name }}', + state: 'absent', + }, + }), }, ], }, diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/compose/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/compose/index.ts index 0b4683f6f7..0b9df5c985 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-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,15 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleApplyComposeTask, + AnsibleCreateComposeTask, AnsibleDockerHostEnvironment, AnsibleHostEndpointCapability, AnsibleOrchestratorOperation, - MetadataGenerated, - MetadataUnfurl, - OpenstackMachineHost, -} from '#technologies/plugins/rules/utils' + AnsibleTouchComposeTask, + AnsibleUnapplyComposeTask, +} from '#technologies/plugins/rules/utils/ansible' +import {DockerCompose} from '#technologies/plugins/rules/utils/compose' +import {MetadataGenerated, MetadataUnfurl, OpenstackMachineHost} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.dbms', @@ -18,32 +21,16 @@ 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 }}', - }, - }, + const suffix = '{{ SELF.dbms_name}}' + const manifest: DockerCompose = { + 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 }}', }, }, }, @@ -91,14 +78,10 @@ const generator: ImplementationGenerator = { inputs: { playbook: { q: [ - AnsibleTouchComposeTask, - AnsibleCreateComposeTask, + AnsibleTouchComposeTask({suffix}), + AnsibleCreateComposeTask({manifest}), { - name: 'apply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', - args: { - executable: '/usr/bin/bash', - }, + ...AnsibleApplyComposeTask(), environment: { ...AnsibleDockerHostEnvironment(), }, @@ -120,14 +103,10 @@ const generator: ImplementationGenerator = { inputs: { playbook: { q: [ - AnsibleTouchComposeTask, - AnsibleCreateComposeTask, + AnsibleTouchComposeTask({suffix}), + AnsibleCreateComposeTask({manifest}), { - name: 'unapply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', - args: { - executable: '/usr/bin/bash', - }, + ...AnsibleUnapplyComposeTask(), environment: { ...AnsibleDockerHostEnvironment(), }, diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/terraform/index.ts index cea9c54f49..b246d551d3 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/terraform/index.ts @@ -1,12 +1,18 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleHostEndpointCapability} from '#technologies/plugins/rules/utils/ansible' import { - AnsibleHostEndpointCapability, + TerraformDockerProviderImport, + TerraformDockerProviderRemoteConfiguration, + TerraformRequiredVersion, + TerraformStandardOperations, +} from '#technologies/plugins/rules/utils/terraform' +import { + LOCALHOST, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, OpenstackMachineHost, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.dbms', @@ -31,7 +37,7 @@ const generator: ImplementationGenerator = { attributes: { application_address: { type: 'string', - default: '127.0.0.1', + default: LOCALHOST, }, application_port: { type: 'integer', @@ -61,29 +67,17 @@ const generator: ImplementationGenerator = { required_providers: [ { docker: { - source: 'kreuzwerker/docker', - version: '3.0.2', + ...TerraformDockerProviderImport(), }, }, ], + ...TerraformRequiredVersion(), }, ], provider: { docker: [ { - host: 'ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22', - ssh_opts: [ - '-i', - '{{ SELF.os_ssh_key_file }}', - '-o', - 'IdentitiesOnly=yes', - '-o', - 'BatchMode=yes', - '-o', - 'UserKnownHostsFile=/dev/null', - '-o', - 'StrictHostKeyChecking=no', - ], + ...TerraformDockerProviderRemoteConfiguration(), }, ], }, diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/gcp-cloudsql/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/gcp-cloudsql/ansible/index.ts index ba1f11e739..c45f2141f4 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/gcp-cloudsql/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/gcp-cloudsql/ansible/index.ts @@ -1,11 +1,7 @@ import * as files from '#files' import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - AnsibleOrchestratorOperation, - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.dbms', diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/gcp-cloudsql/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/gcp-cloudsql/terraform/index.ts index ebb08c30c0..d9e50d32ee 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/gcp-cloudsql/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/gcp-cloudsql/terraform/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.dbms', 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 d07b91269b..d9df5eaf72 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 @@ -2,10 +2,8 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleKubernetesCredentialsEnvironment, AnsibleOrchestratorOperation, - KubernetesCredentials, - MetadataGenerated, - MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/ansible' +import {KubernetesCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.dbms', 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 725d609889..9b1f6f97d4 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,11 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' import { - AnsibleOrchestratorOperation, BASH_KUBECTL, KubernetesCredentials, MetadataGenerated, MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.dbms', diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/terraform/index.ts index adeafe74d2..4099949bce 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/terraform/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - KubernetesCredentials, - MetadataGenerated, - MetadataUnfurl, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import {KubernetesCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.dbms', 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 e5553f7616..7461c2d2b5 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 @@ -5,10 +5,8 @@ import { AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, AnsibleWaitForSSHTask, - MetadataGenerated, - MetadataUnfurl, - OpenstackMachineCredentials, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/ansible' +import {MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials} from '#technologies/plugins/rules/utils/utils' // TODO: ensure dbms_version is installed diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/terraform/index.ts index e9ed192051..0885dbdb3a 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/terraform/index.ts @@ -1,13 +1,13 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleHostEndpointCapability} from '#technologies/plugins/rules/utils/ansible' +import {TerraformSSHConnection, TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { - AnsibleHostEndpointCapability, BASH_HEADER, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, OpenstackMachineHost, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const script = ` ${BASH_HEADER} @@ -105,10 +105,7 @@ const generator: ImplementationGenerator = { { connection: [ { - host: '{{ SELF.os_ssh_host }}', - private_key: '${file("{{ SELF.os_ssh_key_file }}")}', - type: 'ssh', - user: '{{ SELF.os_ssh_user }}', + ...TerraformSSHConnection(), }, ], provisioner: { diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/ansible/index.ts index e7f11ab0a0..d209c9af45 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/ansible/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - AnsibleOrchestratorOperation, - MetadataGenerated, - MetadataUnfurl, - mapProperties, -} from '#technologies/plugins/rules/utils' +import {AnsibleDockerContainerTask, AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {ApplicationProperties, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this @@ -41,13 +37,15 @@ const generator: ImplementationGenerator = { playbook: { q: [ { - name: 'start container', - 'community.docker.docker_container': { - name: '{{ SELF.application_name }}', - image: '{{ ".artifacts::docker_image::file" | eval }}', - network_mode: 'host', - env: mapProperties(type, {format: 'map'}), - }, + ...AnsibleDockerContainerTask({ + name: 'start container', + container: { + name: '{{ SELF.application_name }}', + image: '{{ ".artifacts::docker_image::file" | eval }}', + network_mode: 'host', + env: ApplicationProperties(type).toMap(), + }, + }), }, ], }, @@ -61,11 +59,13 @@ const generator: ImplementationGenerator = { playbook: { q: [ { - name: 'stop container', - 'community.docker.docker_container': { - name: '{{ SELF.application_name }}', - state: 'absent', - }, + ...AnsibleDockerContainerTask({ + name: 'stop container', + container: { + name: '{{ SELF.application_name }}', + state: 'absent', + }, + }), }, ], }, diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/compose/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/compose/index.ts index d2c956121d..32a3608311 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/compose/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/compose/index.ts @@ -1,10 +1,13 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleApplyComposeTask, + AnsibleCreateComposeTask, AnsibleOrchestratorOperation, - MetadataGenerated, - MetadataUnfurl, - mapProperties, -} from '#technologies/plugins/rules/utils' + AnsibleTouchComposeTask, + AnsibleUnapplyComposeTask, +} from '#technologies/plugins/rules/utils/ansible' +import {DockerCompose} from '#technologies/plugins/rules/utils/compose' +import {ApplicationProperties, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this @@ -18,31 +21,16 @@ 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 suffix = '{{ SELF.application_name }}' - 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'}), - }, - }, + const manifest: DockerCompose = { + name: '{{ SELF.application_name }}', + services: { + application: { + container_name: '{{ SELF.application_name }}', + image: '{{ ".artifacts::docker_image::file" | eval }}', + network_mode: 'host', + environment: ApplicationProperties(type).toMap(), }, }, } @@ -69,14 +57,14 @@ const generator: ImplementationGenerator = { inputs: { playbook: { q: [ - AnsibleTouchComposeTask, - AnsibleCreateComposeTask, { - name: 'apply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', - args: { - executable: '/usr/bin/bash', - }, + ...AnsibleTouchComposeTask({suffix}), + }, + { + ...AnsibleCreateComposeTask({manifest}), + }, + { + ...AnsibleApplyComposeTask(), }, ], }, @@ -89,14 +77,14 @@ const generator: ImplementationGenerator = { inputs: { playbook: { q: [ - AnsibleTouchComposeTask, - AnsibleCreateComposeTask, { - name: 'apply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', - args: { - executable: '/usr/bin/bash', - }, + ...AnsibleTouchComposeTask({suffix}), + }, + { + ...AnsibleCreateComposeTask({manifest}), + }, + { + ...AnsibleUnapplyComposeTask(), }, ], }, diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/terraform/index.ts index 61488ee748..1f10db6dd8 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/local-machine/terraform/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - MetadataGenerated, - MetadataUnfurl, - TerraformStandardOperations, - mapProperties, -} from '#technologies/plugins/rules/utils' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import {ApplicationProperties, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this @@ -58,7 +54,7 @@ const generator: ImplementationGenerator = { docker_container: { application: [ { - env: mapProperties(type, {format: 'env', quote: false}), + env: ApplicationProperties(type, {quote: false}).toEnv(), image: '${docker_image.image.image_id}', name: '{{ SELF.application_name }}', network_mode: 'host', diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/ansible/index.ts index e04abd09cf..adf223dc2d 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/ansible/index.ts @@ -1,13 +1,16 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleDockerContainerTask, AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, AnsibleWaitForSSHTask, +} from '#technologies/plugins/rules/utils/ansible' +import { + ApplicationProperties, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, - mapProperties, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this @@ -48,13 +51,15 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - name: 'start container', - 'community.docker.docker_container': { - name: '{{ SELF.application_name }}', - image: '{{ ".artifacts::docker_image::file" | eval }}', - network_mode: 'host', - env: mapProperties(type, {format: 'map'}), - }, + ...AnsibleDockerContainerTask({ + name: 'start container', + container: { + name: '{{ SELF.application_name }}', + image: '{{ ".artifacts::docker_image::file" | eval }}', + network_mode: 'host', + env: ApplicationProperties(type).toMap(), + }, + }), }, ], }, @@ -72,11 +77,13 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - name: 'stop container', - 'community.docker.docker_container': { - name: '{{ SELF.application_name }}', - state: 'absent', - }, + ...AnsibleDockerContainerTask({ + name: 'stop container', + container: { + name: '{{ SELF.application_name }}', + state: 'absent', + }, + }), }, ], }, diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/compose/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/compose/index.ts index 139df5de44..150a489fb0 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/compose/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/compose/index.ts @@ -1,12 +1,16 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleApplyComposeTask, AnsibleDockerHostEnvironment, AnsibleOrchestratorOperation, + AnsibleUnapplyComposeTask, +} from '#technologies/plugins/rules/utils/ansible' +import { + ApplicationProperties, MetadataGenerated, MetadataUnfurl, OpenstackMachineHost, - mapProperties, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this @@ -42,7 +46,7 @@ const generator: ImplementationGenerator = { container_name: '{{ SELF.application_name }}', image: '{{ ".artifacts::docker_image::file" | eval }}', network_mode: 'host', - environment: mapProperties(type, {format: 'map'}), + environment: ApplicationProperties(type).toMap(), }, }, }, @@ -77,11 +81,7 @@ const generator: ImplementationGenerator = { AnsibleTouchComposeTask, AnsibleCreateComposeTask, { - name: 'apply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', - args: { - executable: '/usr/bin/bash', - }, + ...AnsibleApplyComposeTask(), environment: { ...AnsibleDockerHostEnvironment(), }, @@ -100,11 +100,7 @@ const generator: ImplementationGenerator = { AnsibleTouchComposeTask, AnsibleCreateComposeTask, { - name: 'apply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', - args: { - executable: '/usr/bin/bash', - }, + ...AnsibleUnapplyComposeTask(), environment: { ...AnsibleDockerHostEnvironment(), }, diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/terraform/index.ts index 9f7520b8e3..649eee3294 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/docker-engine/remote-machine/terraform/index.ts @@ -1,12 +1,12 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { + ApplicationProperties, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, OpenstackMachineHost, - TerraformStandardOperations, - mapProperties, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this @@ -76,7 +76,7 @@ const generator: ImplementationGenerator = { docker_container: { application: [ { - env: mapProperties(type, {format: 'env', quote: false}), + env: ApplicationProperties(type, {quote: false}).toEnv(), image: '${docker_image.image.image_id}', name: '{{ SELF.application_name }}', network_mode: 'host', diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/ansible/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/ansible/index.ts index d2cbb70454..fb06c98094 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/ansible/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - AnsibleOrchestratorOperation, - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this, see https://docs.ansible.com/ansible/latest/collections/google/cloud/gcp_redis_instance_module.html diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/terraform/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/terraform/index.ts index 8f2403ad52..70b72cf220 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/terraform/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this, see https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/redis_instance diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts index d554e42727..f3bfb01f2f 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - AnsibleOrchestratorOperation, - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, -} from '#technologies/plugins/rules/utils' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts index 26a6fd2286..9fe03d4a46 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - GCPProviderCredentials, - MetadataGenerated, - MetadataUnfurl, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import {GCPProviderCredentials, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: next: implement this, see https://registry.terraform.io/providers/aminueza/minio/latest diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/ansible/index.ts index 994fb21b7c..e2bde285d3 100644 --- a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/ansible/index.ts @@ -1,10 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - AnsibleOrchestratorOperation, - MetadataGenerated, - MetadataUnfurl, - mapProperties, -} from '#technologies/plugins/rules/utils' +import {AnsibleDockerContainerTask, AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {ApplicationProperties, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'service.application', @@ -39,13 +35,15 @@ const generator: ImplementationGenerator = { playbook: { q: [ { - name: 'start container', - 'community.docker.docker_container': { - name: '{{ SELF.application_name }}', - image: '{{ ".artifacts::docker_image::file" | eval }}', - network_mode: 'host', - env: mapProperties(type, {format: 'map'}), - }, + ...AnsibleDockerContainerTask({ + name: 'start container', + container: { + name: '{{ SELF.application_name }}', + image: '{{ ".artifacts::docker_image::file" | eval }}', + network_mode: 'host', + env: ApplicationProperties(type).toMap(), + }, + }), }, ], }, @@ -59,11 +57,13 @@ const generator: ImplementationGenerator = { playbook: { q: [ { - name: 'stop container', - 'community.docker.docker_container': { - name: '{{ SELF.application_name }}', - state: 'absent', - }, + ...AnsibleDockerContainerTask({ + name: 'stop container', + container: { + name: '{{ SELF.application_name }}', + state: 'absent', + }, + }), }, ], }, diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/compose/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/compose/index.ts index e87454877e..44d876a093 100644 --- a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/compose/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/compose/index.ts @@ -1,10 +1,13 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleApplyComposeTask, + AnsibleCreateComposeTask, AnsibleOrchestratorOperation, - MetadataGenerated, - MetadataUnfurl, - mapProperties, -} from '#technologies/plugins/rules/utils' + AnsibleTouchComposeTask, + AnsibleUnapplyComposeTask, +} from '#technologies/plugins/rules/utils/ansible' +import {DockerCompose} from '#technologies/plugins/rules/utils/compose' +import {ApplicationProperties, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'service.application', @@ -16,31 +19,15 @@ 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'}), - }, - }, + const suffix = '{{ SELF.application_name }}' + const manifest: DockerCompose = { + name: '{{ SELF.application_name }}', + services: { + application: { + container_name: '{{ SELF.application_name }}', + image: '{{ ".artifacts::docker_image::file" | eval }}', + network_mode: 'host', + environment: ApplicationProperties(type).toMap(), }, }, } @@ -67,14 +54,14 @@ const generator: ImplementationGenerator = { inputs: { playbook: { q: [ - AnsibleTouchComposeTask, - AnsibleCreateComposeTask, { - name: 'apply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', - args: { - executable: '/usr/bin/bash', - }, + ...AnsibleTouchComposeTask({suffix}), + }, + { + ...AnsibleCreateComposeTask({manifest}), + }, + { + ...AnsibleApplyComposeTask(), }, ], }, @@ -87,14 +74,14 @@ const generator: ImplementationGenerator = { inputs: { playbook: { q: [ - AnsibleTouchComposeTask, - AnsibleCreateComposeTask, { - name: 'apply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', - args: { - executable: '/usr/bin/bash', - }, + ...AnsibleTouchComposeTask({suffix}), + }, + { + ...AnsibleCreateComposeTask({manifest}), + }, + { + ...AnsibleUnapplyComposeTask(), }, ], }, diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/terraform/index.ts index ffe868adab..52823ca062 100644 --- a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/local-machine/terraform/index.ts @@ -1,10 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { - MetadataGenerated, - MetadataUnfurl, + TerraformDockerProviderImport, + TerraformDockerProviderLocalConfiguration, + TerraformRequiredVersion, TerraformStandardOperations, - mapProperties, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/terraform' +import {ApplicationProperties, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'service.application', @@ -38,17 +39,17 @@ const generator: ImplementationGenerator = { required_providers: [ { docker: { - source: 'kreuzwerker/docker', - version: '3.0.2', + ...TerraformDockerProviderImport(), }, }, ], + ...TerraformRequiredVersion(), }, ], provider: { docker: [ { - host: 'unix:///var/run/docker.sock', + ...TerraformDockerProviderLocalConfiguration(), }, ], }, @@ -56,7 +57,7 @@ const generator: ImplementationGenerator = { docker_container: { application: [ { - env: mapProperties(type, {format: 'env', quote: false}), + env: ApplicationProperties(type, {quote: false}).toEnv(), image: '${docker_image.image.image_id}', name: '{{ SELF.application_name }}', network_mode: 'host', 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 3538970d79..d77656e681 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 @@ -1,13 +1,17 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleDockerContainerTask, AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, AnsibleWaitForSSHTask, +} from '#technologies/plugins/rules/utils/ansible' +import { + ApplicationProperties, + LOCALHOST, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, - mapProperties, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'service.application', @@ -29,7 +33,7 @@ const generator: ImplementationGenerator = { attributes: { application_address: { type: 'string', - default: '127.0.0.1', + default: LOCALHOST, }, }, interfaces: { @@ -46,13 +50,15 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - name: 'start container', - 'community.docker.docker_container': { - name: '{{ SELF.application_name }}', - image: '{{ ".artifacts::docker_image::file" | eval }}', - network_mode: 'host', - env: mapProperties(type, {format: 'map'}), - }, + ...AnsibleDockerContainerTask({ + name: 'start container', + container: { + name: '{{ SELF.application_name }}', + image: '{{ ".artifacts::docker_image::file" | eval }}', + network_mode: 'host', + env: ApplicationProperties(type).toMap(), + }, + }), }, ], }, @@ -70,11 +76,13 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - name: 'stop container', - 'community.docker.docker_container': { - name: '{{ SELF.application_name }}', - state: 'absent', - }, + ...AnsibleDockerContainerTask({ + name: 'stop container', + container: { + name: '{{ SELF.application_name }}', + state: 'absent', + }, + }), }, ], }, 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 68d7b267b3..daf6cb1b08 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,12 +1,19 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { + AnsibleApplyComposeTask, + AnsibleCreateComposeTask, AnsibleDockerHostEnvironment, AnsibleOrchestratorOperation, + AnsibleTouchComposeTask, + AnsibleUnapplyComposeTask, +} from '#technologies/plugins/rules/utils/ansible' +import {DockerCompose} from '#technologies/plugins/rules/utils/compose' +import { + ApplicationProperties, MetadataGenerated, MetadataUnfurl, OpenstackMachineHost, - mapProperties, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'service.application', @@ -18,31 +25,16 @@ 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 suffix = '{{ SELF.application_name }}' - 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'}), - }, - }, + const manifest: DockerCompose = { + name: '{{ SELF.application_name }}', + services: { + application: { + container_name: '{{ SELF.application_name }}', + image: '{{ ".artifacts::docker_image::file" | eval }}', + network_mode: 'host', + environment: ApplicationProperties(type).toMap(), }, }, } @@ -72,14 +64,14 @@ const generator: ImplementationGenerator = { inputs: { playbook: { q: [ - AnsibleTouchComposeTask, - AnsibleCreateComposeTask, { - name: 'apply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', - args: { - executable: '/usr/bin/bash', - }, + ...AnsibleTouchComposeTask({suffix}), + }, + { + ...AnsibleCreateComposeTask({manifest}), + }, + { + ...AnsibleApplyComposeTask(), environment: { ...AnsibleDockerHostEnvironment(), }, @@ -95,14 +87,14 @@ const generator: ImplementationGenerator = { inputs: { playbook: { q: [ - AnsibleTouchComposeTask, - AnsibleCreateComposeTask, { - name: 'apply compose', - 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', - args: { - executable: '/usr/bin/bash', - }, + ...AnsibleTouchComposeTask({suffix}), + }, + { + ...AnsibleCreateComposeTask({manifest}), + }, + { + ...AnsibleUnapplyComposeTask(), environment: { ...AnsibleDockerHostEnvironment(), }, diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/remote-machine/terraform/index.ts index fa4ddaebaf..afec2f996a 100644 --- a/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/docker-engine/remote-machine/terraform/index.ts @@ -1,12 +1,12 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { + ApplicationProperties, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, OpenstackMachineHost, - TerraformStandardOperations, - mapProperties, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'service.application', @@ -74,7 +74,7 @@ const generator: ImplementationGenerator = { docker_container: { application: [ { - env: mapProperties(type, {format: 'env', quote: false}), + env: ApplicationProperties(type, {quote: false}).toEnv(), image: '${docker_image.image.image_id}', name: '{{ SELF.application_name }}', network_mode: 'host', diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/gcp-cloudrun/ansible/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/gcp-cloudrun/ansible/index.ts index 3832de3e06..bc5537a761 100644 --- a/src/technologies/plugins/rules/generators/service-application/docker-image/gcp-cloudrun/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/gcp-cloudrun/ansible/index.ts @@ -1,14 +1,14 @@ import * as files from '#files' import {ImplementationGenerator, PROPERTIES} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' import { - AnsibleOrchestratorOperation, + ApplicationProperties, GCPProviderCredentials, JinjaSecureApplicationProtocol, MetadataGenerated, MetadataUnfurl, SecureApplicationProtocolPropertyDefinition, - mapProperties, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'service.application', @@ -88,9 +88,9 @@ const generator: ImplementationGenerator = { '{{ SELF.application_port }}', }, ], - env: mapProperties(type, { + env: ApplicationProperties(type, { ignore: [PROPERTIES.PORT], - }), + }).toList(), }, ], }, diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/gcp-cloudrun/terraform/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/gcp-cloudrun/terraform/index.ts index 58c87f1e68..3e6296417e 100644 --- a/src/technologies/plugins/rules/generators/service-application/docker-image/gcp-cloudrun/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/gcp-cloudrun/terraform/index.ts @@ -1,13 +1,13 @@ import {ImplementationGenerator, PROPERTIES} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { + ApplicationProperties, GCPProviderCredentials, JinjaSecureApplicationProtocol, MetadataGenerated, MetadataUnfurl, SecureApplicationProtocolPropertyDefinition, - TerraformStandardOperations, - mapProperties, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' // TODO: application port is now 443 (also applies to other GCP deployments) @@ -91,7 +91,9 @@ const generator: ImplementationGenerator = { container_port: '{{ SELF.application_port }}', }, ], - env: mapProperties(type, {ignore: [PROPERTIES.PORT]}), + env: ApplicationProperties(type, { + ignore: [PROPERTIES.PORT], + }).toList(), }, ], }, 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 ebd88977ae..e8bf8b9e87 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 @@ -2,11 +2,13 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleKubernetesCredentialsEnvironment, AnsibleOrchestratorOperation, +} from '#technologies/plugins/rules/utils/ansible' +import { + ApplicationProperties, KubernetesCredentials, MetadataGenerated, MetadataUnfurl, - mapProperties, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'service.application', @@ -74,7 +76,7 @@ const generator: ImplementationGenerator = { { image: '{{ ".artifacts::docker_image::file" | eval }}', name: '{{ SELF.application_name }}', - env: mapProperties(type), + env: ApplicationProperties(type).toList(), ports: [ { containerPort: 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 c34d9b71de..aefd4a9693 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,11 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' import { - AnsibleOrchestratorOperation, + ApplicationProperties, BASH_KUBECTL, MetadataGenerated, MetadataUnfurl, - mapProperties, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'service.application', @@ -56,7 +56,7 @@ const generator: ImplementationGenerator = { { image: '{{ ".artifacts::docker_image::file" | eval }}', name: '{{ SELF.application_name }}', - env: mapProperties(type), + env: ApplicationProperties(type).toList(), ports: [ { containerPort: '{{ SELF.application_port }}', diff --git a/src/technologies/plugins/rules/generators/service-application/docker-image/kubernetes-cluster/terraform/index.ts b/src/technologies/plugins/rules/generators/service-application/docker-image/kubernetes-cluster/terraform/index.ts index 93bb36d8f6..63e2960e03 100644 --- a/src/technologies/plugins/rules/generators/service-application/docker-image/kubernetes-cluster/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/docker-image/kubernetes-cluster/terraform/index.ts @@ -1,11 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { + ApplicationProperties, KubernetesCredentials, MetadataGenerated, MetadataUnfurl, - TerraformStandardOperations, - mapProperties, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'service.application', @@ -91,7 +91,7 @@ const generator: ImplementationGenerator = { { container: [ { - env: mapProperties(type), + env: ApplicationProperties(type).toList(), image: '{{ ".artifacts::docker_image::file" | eval }}', name: '{{ SELF.application_name }}', port: [ diff --git a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/ansible/index.ts index 384fd32707..aa21e97e91 100644 --- a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/ansible/index.ts @@ -2,8 +2,8 @@ import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleAssertOperationTask, - AnsibleCallOperationTask, - AnsibleCopyOperationTask, + AnsibleCallManagementOperationTask, + AnsibleCopyManagementOperationTask, AnsibleCreateApplicationDirectoryTask, AnsibleCreateApplicationEnvironment, AnsibleCreateApplicationSystemdUnit, @@ -14,11 +14,13 @@ import { AnsibleUnarchiveSourceArchiveFileTask, AnsibleUnarchiveSourceArchiveUrlTask, AnsibleWaitForSSHTask, +} from '#technologies/plugins/rules/utils/ansible' +import { ApplicationDirectory, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const artifact = 'tar.archive' @@ -72,10 +74,10 @@ const generator: ImplementationGenerator = { ...AnsibleCreateApplicationEnvironment(type), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.CREATE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.CREATE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), }, { ...AnsibleCreateApplicationSystemdUnit(), @@ -105,10 +107,10 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), }, ], }, @@ -129,7 +131,7 @@ const generator: ImplementationGenerator = { ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.START), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.START), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.START), }, { name: 'start service', @@ -156,10 +158,10 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.STOP), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.STOP), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), }, { name: 'stop service', @@ -184,10 +186,10 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.DELETE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.DELETE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), }, { name: 'delete systemd service', diff --git a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/terraform/index.ts index 57406379d0..9fbec0532f 100644 --- a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/terraform/index.ts @@ -1,13 +1,14 @@ import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {NodeType} from '#spec/node-type' import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {TerraformSSHConnection, TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { ApplicationDirectory, ApplicationSystemdUnit, BASH_HEADER, - BashAssertOperation, - BashCallOperation, - BashCopyOperation, + BashAssertManagementOperation, + BashCallManagementOperation, + BashCopyManagementOperation, BashCreateApplicationDirectory, BashCreateApplicationEnvironment, BashCreateVintnerDirectory, @@ -19,8 +20,7 @@ import { OpenstackMachineCredentials, OpenstackMachineHost, SourceArchiveFile, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' class Generator extends GeneratorAbstract { component = 'service.application' @@ -51,10 +51,7 @@ class Generator extends GeneratorAbstract { { connection: [ { - host: '{{ SELF.os_ssh_host }}', - private_key: '${file("{{ SELF.os_ssh_key_file }}")}', - type: 'ssh', - user: '{{ SELF.os_ssh_user }}', + ...TerraformSSHConnection(), }, ], provisioner: { @@ -150,10 +147,10 @@ systemctl enable {{ SELF.application_name }} return `${BASH_HEADER} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} ` } @@ -161,7 +158,7 @@ ${BashCallOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} return `${BASH_HEADER} # Assert operation -${BashAssertOperation(MANAGEMENT_OPERATIONS.START)} +${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.START)} # Start service systemctl start {{ SELF.application_name }} @@ -172,13 +169,13 @@ systemctl start {{ SELF.application_name }} return `${BASH_HEADER} # Assert operation -${BashAssertOperation(MANAGEMENT_OPERATIONS.STOP)} +${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.STOP)} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.STOP)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.STOP)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.STOP)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.STOP)} # Stop service systemctl stop {{ SELF.application_name }} @@ -189,10 +186,10 @@ systemctl stop {{ SELF.application_name }} return `${BASH_HEADER} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.DELETE)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.DELETE)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} # Delete application directory ${BashDeleteApplicationDirectory()} diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/ansible/index.ts index 913ae206e2..05929f2381 100644 --- a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/ansible/index.ts @@ -2,8 +2,8 @@ import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleAssertOperationTask, - AnsibleCallOperationTask, - AnsibleCopyOperationTask, + AnsibleCallManagementOperationTask, + AnsibleCopyManagementOperationTask, AnsibleCreateApplicationDirectoryTask, AnsibleCreateApplicationEnvironment, AnsibleCreateApplicationSystemdUnit, @@ -13,11 +13,13 @@ import { AnsibleHostOperationPlaybookArgs, AnsibleUnarchiveSourceArchiveFileTask, AnsibleWaitForSSHTask, +} from '#technologies/plugins/rules/utils/ansible' +import { ApplicationDirectory, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const artifact = 'zip.archive' @@ -78,10 +80,10 @@ const generator: ImplementationGenerator = { ...AnsibleCreateApplicationEnvironment(type), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.CREATE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.CREATE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), }, { ...AnsibleCreateApplicationSystemdUnit(), @@ -111,10 +113,10 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), }, ], }, @@ -135,7 +137,7 @@ const generator: ImplementationGenerator = { ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.START), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.START), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.START), }, { name: 'start service', @@ -162,10 +164,10 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.STOP), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.STOP), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), }, { name: 'stop service', @@ -190,10 +192,10 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.DELETE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.DELETE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), }, { name: 'delete systemd service', diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/terraform/index.ts index 2386167efb..324bcc946e 100644 --- a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/terraform/index.ts @@ -1,13 +1,14 @@ import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {NodeType} from '#spec/node-type' import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {TerraformSSHConnection, TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { ApplicationDirectory, ApplicationSystemdUnit, BASH_HEADER, - BashAssertOperation, - BashCallOperation, - BashCopyOperation, + BashAssertManagementOperation, + BashCallManagementOperation, + BashCopyManagementOperation, BashCreateApplicationDirectory, BashCreateApplicationEnvironment, BashCreateVintnerDirectory, @@ -19,8 +20,7 @@ import { OpenstackMachineCredentials, OpenstackMachineHost, SourceArchiveFile, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' class Generator extends GeneratorAbstract { component = 'service.application' @@ -51,10 +51,7 @@ class Generator extends GeneratorAbstract { { connection: [ { - host: '{{ SELF.os_ssh_host }}', - private_key: '${file("{{ SELF.os_ssh_key_file }}")}', - type: 'ssh', - user: '{{ SELF.os_ssh_user }}', + ...TerraformSSHConnection(), }, ], provisioner: { @@ -150,10 +147,10 @@ systemctl enable {{ SELF.application_name }} return `${BASH_HEADER} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} ` } @@ -161,7 +158,7 @@ ${BashCallOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} return `${BASH_HEADER} # Assert operation -${BashAssertOperation(MANAGEMENT_OPERATIONS.START)} +${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.START)} # Start service systemctl start {{ SELF.application_name }} @@ -172,13 +169,13 @@ systemctl start {{ SELF.application_name }} return `${BASH_HEADER} # Assert operation -${BashAssertOperation(MANAGEMENT_OPERATIONS.STOP)} +${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.STOP)} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.STOP)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.STOP)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.STOP)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.STOP)} # Stop service systemctl stop {{ SELF.application_name }} @@ -189,10 +186,10 @@ systemctl stop {{ SELF.application_name }} return `${BASH_HEADER} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.DELETE)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.DELETE)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} # Delete application directory ${BashDeleteApplicationDirectory()} diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/gcp-appengine/ansible/index.ts b/src/technologies/plugins/rules/generators/service-application/zip-archive/gcp-appengine/ansible/index.ts index 558dbde701..dba4ee487e 100644 --- a/src/technologies/plugins/rules/generators/service-application/zip-archive/gcp-appengine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/zip-archive/gcp-appengine/ansible/index.ts @@ -1,15 +1,15 @@ import * as files from '#files' import {ImplementationGenerator, PROPERTIES} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' import { - AnsibleOrchestratorOperation, + ApplicationProperties, GCPProviderCredentials, JinjaSecureApplicationProtocol, MetadataGenerated, MetadataUnfurl, SecureApplicationProtocolPropertyDefinition, SourceArchiveFile, - mapProperties, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' // TODO: port is now 443 @@ -94,10 +94,9 @@ const generator: ImplementationGenerator = { runtime: '{{ SELF.application_language }}', service: '{{ SELF.application_name }}', instance_class: 'F1', - env_variables: mapProperties(type, { - format: 'map', + env_variables: ApplicationProperties(type, { ignore: [PROPERTIES.PORT], - }), + }).toMap(), }, }, }, diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/gcp-appengine/terraform/index.ts b/src/technologies/plugins/rules/generators/service-application/zip-archive/gcp-appengine/terraform/index.ts index e0aa257117..d895da68ee 100644 --- a/src/technologies/plugins/rules/generators/service-application/zip-archive/gcp-appengine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/zip-archive/gcp-appengine/terraform/index.ts @@ -1,16 +1,16 @@ import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {ImplementationGenerator, PROPERTIES} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { + ApplicationProperties, GCPProviderCredentials, JinjaSecureApplicationProtocol, MetadataGenerated, MetadataUnfurl, SecureApplicationProtocolPropertyDefinition, - SelfOperation, + SelfManagementOperation, SourceArchiveFile, - TerraformStandardOperations, - mapProperties, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' // TODO: application port is now 443 @@ -96,13 +96,14 @@ const generator: ImplementationGenerator = { ], entrypoint: [ { - shell: `{{ ${SelfOperation(MANAGEMENT_OPERATIONS.START)} }}`, + shell: `{{ ${SelfManagementOperation( + MANAGEMENT_OPERATIONS.START + )} }}`, }, ], - env_variables: mapProperties(type, { - format: 'map', + env_variables: ApplicationProperties(type, { ignore: [PROPERTIES.PORT], - }), + }).toMap(), runtime: '{{ SELF.application_language }}', service: '{{ SELF.application_name }}', service_account: '${google_service_account.custom_service_account.email}', diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/ansible/index.ts index 5cca2768b8..70656e7abe 100644 --- a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/ansible/index.ts @@ -1,18 +1,20 @@ import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { - AnsibleCallOperationTask, - AnsibleCopyOperationTask, + AnsibleCallManagementOperationTask, + AnsibleCopyManagementOperationTask, AnsibleCreateApplicationDirectoryTask, AnsibleDeleteApplicationDirectoryTask, AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, AnsibleWaitForSSHTask, +} from '#technologies/plugins/rules/utils/ansible' +import { ApplicationDirectory, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'software.application', @@ -103,10 +105,10 @@ const generator: ImplementationGenerator = { ...AnsibleCreateApplicationDirectoryTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.CREATE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.CREATE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), }, ], }, @@ -124,10 +126,10 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), }, ], }, @@ -145,10 +147,10 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.START), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.START), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.START), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.START), }, ], }, @@ -166,10 +168,10 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.STOP), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.STOP), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), }, ], }, @@ -187,10 +189,10 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.DELETE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.DELETE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), }, { ...AnsibleDeleteApplicationDirectoryTask(), diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/terraform/index.ts index 4a11d4c34f..a5549f8401 100644 --- a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/terraform/index.ts @@ -1,11 +1,12 @@ import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {NodeType} from '#spec/node-type' import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {TerraformSSHConnection, TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { ApplicationDirectory, BASH_HEADER, - BashCallOperation, - BashCopyOperation, + BashCallManagementOperation, + BashCopyManagementOperation, BashCreateApplicationDirectory, BashCreateApplicationEnvironment, BashCreateVintnerDirectory, @@ -15,8 +16,7 @@ import { MetadataGenerated, OpenstackMachineCredentials, OpenstackMachineHost, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' class Generator extends GeneratorAbstract { component = 'software.application' @@ -47,10 +47,7 @@ class Generator extends GeneratorAbstract { { connection: [ { - host: '{{ SELF.os_ssh_host }}', - private_key: '${file("{{ SELF.os_ssh_key_file }}")}', - type: 'ssh', - user: '{{ SELF.os_ssh_user }}', + ...TerraformSSHConnection(), }, ], provisioner: { @@ -149,10 +146,10 @@ ${BashUnarchiveSourceArchiveFile(name, this.artifact)} ${BashCreateVintnerDirectory()} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.CREATE)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.CREATE)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} ` } @@ -160,10 +157,10 @@ ${BashCallOperation(MANAGEMENT_OPERATIONS.CREATE)} return `${BASH_HEADER} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} ` } @@ -171,10 +168,10 @@ ${BashCallOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} return `${BASH_HEADER} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.START)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.START)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.START)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.START)} ` } @@ -182,10 +179,10 @@ ${BashCallOperation(MANAGEMENT_OPERATIONS.START)} return `${BASH_HEADER} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.STOP)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.STOP)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.STOP)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.STOP)} ` } @@ -193,10 +190,10 @@ ${BashCallOperation(MANAGEMENT_OPERATIONS.STOP)} return `${BASH_HEADER} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.DELETE)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.DELETE)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} # Delete application directory ${BashDeleteApplicationDirectory()} diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/ansible/index.ts index f38be0edb1..e5fd18e86c 100644 --- a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/ansible/index.ts @@ -2,8 +2,8 @@ import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleAssertOperationTask, - AnsibleCallOperationTask, - AnsibleCopyOperationTask, + AnsibleCallManagementOperationTask, + AnsibleCopyManagementOperationTask, AnsibleCreateApplicationDirectoryTask, AnsibleCreateApplicationEnvironment, AnsibleCreateVintnerDirectory, @@ -13,11 +13,13 @@ import { AnsibleUnarchiveSourceArchiveFileTask, AnsibleUnarchiveSourceArchiveUrlTask, AnsibleWaitForSSHTask, +} from '#technologies/plugins/rules/utils/ansible' +import { ApplicationDirectory, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const artifact = 'tar.archive' @@ -71,10 +73,10 @@ const generator: ImplementationGenerator = { ...AnsibleCreateApplicationEnvironment(type), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.CREATE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.CREATE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), }, ], }, @@ -92,10 +94,10 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), }, ], }, @@ -116,10 +118,10 @@ const generator: ImplementationGenerator = { ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.START), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.START), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.START), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.START), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.START), }, ], }, @@ -140,10 +142,10 @@ const generator: ImplementationGenerator = { ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.STOP), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.STOP), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.STOP), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), }, ], }, @@ -161,10 +163,10 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.DELETE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.DELETE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), }, { ...AnsibleDeleteApplicationDirectoryTask(), diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/terraform/index.ts index b0cb6e4020..10fed34ded 100644 --- a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/terraform/index.ts @@ -1,12 +1,13 @@ import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {NodeType} from '#spec/node-type' import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {TerraformSSHConnection, TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { ApplicationDirectory, BASH_HEADER, - BashAssertOperation, - BashCallOperation, - BashCopyOperation, + BashAssertManagementOperation, + BashCallManagementOperation, + BashCopyManagementOperation, BashCreateApplicationDirectory, BashCreateApplicationEnvironment, BashCreateVintnerDirectory, @@ -18,8 +19,7 @@ import { OpenstackMachineCredentials, OpenstackMachineHost, SourceArchiveFile, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' class Generator extends GeneratorAbstract { component = 'software.application' @@ -50,10 +50,7 @@ class Generator extends GeneratorAbstract { { connection: [ { - host: '{{ SELF.os_ssh_host }}', - private_key: '${file("{{ SELF.os_ssh_key_file }}")}', - type: 'ssh', - user: '{{ SELF.os_ssh_user }}', + ...TerraformSSHConnection(), }, ], provisioner: { @@ -133,10 +130,10 @@ ${BashUnarchiveSourceArchiveFile(name, this.artifact)} ${BashCreateVintnerDirectory()} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.CREATE)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.CREATE)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} ` } @@ -144,10 +141,10 @@ ${BashCallOperation(MANAGEMENT_OPERATIONS.CREATE)} return `${BASH_HEADER} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} ` } @@ -155,13 +152,13 @@ ${BashCallOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} return `${BASH_HEADER} # Assert operation -${BashAssertOperation(MANAGEMENT_OPERATIONS.START)} +${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.START)} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.START)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.START)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.START)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.START)} ` } @@ -169,13 +166,13 @@ ${BashCallOperation(MANAGEMENT_OPERATIONS.START)} return `${BASH_HEADER} # Assert operation -${BashAssertOperation(MANAGEMENT_OPERATIONS.STOP)} +${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.STOP)} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.STOP)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.STOP)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.STOP)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.STOP)} ` } @@ -183,10 +180,10 @@ ${BashCallOperation(MANAGEMENT_OPERATIONS.STOP)} return `${BASH_HEADER} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.DELETE)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.DELETE)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} # Delete application directory ${BashDeleteApplicationDirectory()} diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/ansible/index.ts index b3e14b6ce4..b214c17051 100644 --- a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/ansible/index.ts @@ -2,8 +2,8 @@ import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleAssertOperationTask, - AnsibleCallOperationTask, - AnsibleCopyOperationTask, + AnsibleCallManagementOperationTask, + AnsibleCopyManagementOperationTask, AnsibleCreateApplicationDirectoryTask, AnsibleCreateApplicationEnvironment, AnsibleCreateVintnerDirectory, @@ -12,11 +12,13 @@ import { AnsibleHostOperationPlaybookArgs, AnsibleUnarchiveSourceArchiveFileTask, AnsibleWaitForSSHTask, +} from '#technologies/plugins/rules/utils/ansible' +import { ApplicationDirectory, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const artifact = 'zip.archive' @@ -77,10 +79,10 @@ const generator: ImplementationGenerator = { ...AnsibleCreateApplicationEnvironment(type), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.CREATE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.CREATE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), }, ], }, @@ -98,10 +100,10 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), }, ], }, @@ -122,10 +124,10 @@ const generator: ImplementationGenerator = { ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.START), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.START), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.START), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.START), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.START), }, ], }, @@ -146,10 +148,10 @@ const generator: ImplementationGenerator = { ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.STOP), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.STOP), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.STOP), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), }, ], }, @@ -167,10 +169,10 @@ const generator: ImplementationGenerator = { ...AnsibleWaitForSSHTask(), }, { - ...AnsibleCopyOperationTask(MANAGEMENT_OPERATIONS.DELETE), + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), }, { - ...AnsibleCallOperationTask(MANAGEMENT_OPERATIONS.DELETE), + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), }, { ...AnsibleDeleteApplicationDirectoryTask(), diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/terraform/index.ts index 90c8e85103..4e550ce67a 100644 --- a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/terraform/index.ts @@ -1,12 +1,13 @@ import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {NodeType} from '#spec/node-type' import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {TerraformSSHConnection, TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { ApplicationDirectory, BASH_HEADER, - BashAssertOperation, - BashCallOperation, - BashCopyOperation, + BashAssertManagementOperation, + BashCallManagementOperation, + BashCopyManagementOperation, BashCreateApplicationDirectory, BashCreateApplicationEnvironment, BashCreateVintnerDirectory, @@ -18,8 +19,7 @@ import { OpenstackMachineCredentials, OpenstackMachineHost, SourceArchiveFile, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' export class Generator extends GeneratorAbstract { component = 'software.application' @@ -50,10 +50,7 @@ export class Generator extends GeneratorAbstract { { connection: [ { - host: '{{ SELF.os_ssh_host }}', - private_key: '${file("{{ SELF.os_ssh_key_file }}")}', - type: 'ssh', - user: '{{ SELF.os_ssh_user }}', + ...TerraformSSHConnection(), }, ], provisioner: { @@ -133,10 +130,10 @@ ${BashUnarchiveSourceArchiveFile(name, this.artifact)} ${BashCreateVintnerDirectory()} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.CREATE)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.CREATE)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} ` } @@ -144,10 +141,10 @@ ${BashCallOperation(MANAGEMENT_OPERATIONS.CREATE)} return `${BASH_HEADER} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} ` } @@ -155,13 +152,13 @@ ${BashCallOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} return `${BASH_HEADER} # Assert operation -${BashAssertOperation(MANAGEMENT_OPERATIONS.START)} +${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.START)} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.START)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.START)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.START)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.START)} ` } @@ -169,13 +166,13 @@ ${BashCallOperation(MANAGEMENT_OPERATIONS.START)} return `${BASH_HEADER} # Assert operation -${BashAssertOperation(MANAGEMENT_OPERATIONS.STOP)} +${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.STOP)} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.STOP)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.STOP)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.STOP)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.STOP)} ` } @@ -183,10 +180,10 @@ ${BashCallOperation(MANAGEMENT_OPERATIONS.STOP)} return `${BASH_HEADER} # Copy operation -${BashCopyOperation(MANAGEMENT_OPERATIONS.DELETE)} +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} # Execute operation -${BashCallOperation(MANAGEMENT_OPERATIONS.DELETE)} +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} # Delete application directory ${BashDeleteApplicationDirectory()} diff --git a/src/technologies/plugins/rules/generators/virtual-machine/openstack-provider/ansible/index.ts b/src/technologies/plugins/rules/generators/virtual-machine/openstack-provider/ansible/index.ts index c595aa4413..4106df5a32 100644 --- a/src/technologies/plugins/rules/generators/virtual-machine/openstack-provider/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/virtual-machine/openstack-provider/ansible/index.ts @@ -1,12 +1,12 @@ import * as files from '#files' import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' import { - AnsibleOrchestratorOperation, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, OpenstackProviderCredentials, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'virtual.machine', diff --git a/src/technologies/plugins/rules/generators/virtual-machine/openstack-provider/terraform/index.ts b/src/technologies/plugins/rules/generators/virtual-machine/openstack-provider/terraform/index.ts index a60c25a8d7..7d38cbcc90 100644 --- a/src/technologies/plugins/rules/generators/virtual-machine/openstack-provider/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/virtual-machine/openstack-provider/terraform/index.ts @@ -1,11 +1,11 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {TerraformRequiredVersion, TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, OpenstackProviderCredentials, - TerraformStandardOperations, -} from '#technologies/plugins/rules/utils' +} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'virtual.machine', @@ -46,7 +46,7 @@ const generator: ImplementationGenerator = { }, }, ], - required_version: '>= 0.14.0', + ...TerraformRequiredVersion(), }, ], provider: { diff --git a/src/technologies/plugins/rules/utils/ansible.ts b/src/technologies/plugins/rules/utils/ansible.ts new file mode 100644 index 0000000000..ee01b63414 --- /dev/null +++ b/src/technologies/plugins/rules/utils/ansible.ts @@ -0,0 +1,339 @@ +import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' +import {NodeType} from '#spec/node-type' +import {DockerCompose} from '#technologies/plugins/rules/utils/compose' +import { + ApplicationEnvironment, + ApplicationSystemdUnit, + JinjaWhenManagementOperationDefined, + JinjaWhenManagementOperationUndefined, + JinjaWhenSourceArchiveFile, + JinjaWhenSourceArchiveUrl, + ManagementOperation, + SourceArchiveExtraOpts, + SourceArchiveFile, + SourceArchiveUrl, +} from '#technologies/plugins/rules/utils/utils' + +export type AnsibleTaskOptions = { + name: string + when?: string + register?: string +} + +export type AnsibleModuleOptions = { + name: string + state?: 'present' | 'absent' +} + +export function AnsibleHostEndpointCapability() { + return { + endpoint: { + type: 'unfurl.capabilities.Endpoint.Ansible', + properties: { + connection: 'ssh', + host: {eval: '.parent::management_address'}, + }, + }, + } +} + +export function AnsibleHostOperation() { + return { + primary: 'Ansible', + operation_host: 'HOST', + environment: { + ANSIBLE_HOST_KEY_CHECKING: 'False', + }, + } +} + +export function AnsibleOrchestratorOperation() { + return { + primary: 'Ansible', + operation_host: 'ORCHESTRATOR', + } +} + +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 AnsibleGCPCredentialsEnvironment() { + return { + GCP_SERVICE_ACCOUNT_FILE: { + eval: '.::gcp_service_account_file', + }, + GCP_AUTH_KIND: 'serviceaccount', + } +} + +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 }}'] +} + +export function AnsibleWaitForSSHTask() { + return { + name: 'wait for ssh', + wait_for_connection: null, + } +} + +export function AnsibleCreateApplicationDirectoryTask() { + return { + name: 'create application directory', + 'ansible.builtin.file': { + path: '{{ SELF.application_directory }}', + state: 'directory', + }, + } +} + +export function AnsibleDeleteApplicationDirectoryTask() { + return { + name: 'delete application directory', + 'ansible.builtin.file': { + path: '{{ SELF.application_directory }}', + state: 'absent', + }, + } +} + +export function AnsibleUnarchiveSourceArchiveFileTask(type: string) { + return { + name: 'extract deployment artifact in application directory', + 'ansible.builtin.unarchive': { + src: SourceArchiveFile(type), + dest: '{{ SELF.application_directory }}', + extra_opts: SourceArchiveExtraOpts(type), + }, + when: JinjaWhenSourceArchiveFile(type), + } +} + +export function AnsibleUnarchiveSourceArchiveUrlTask(type: string) { + return { + name: 'extract deployment artifact from URL in application directory', + 'ansible.builtin.unarchive': { + src: SourceArchiveUrl(type), + dest: '{{ SELF.application_directory }}', + remote_src: 'yes', + extra_opts: SourceArchiveExtraOpts(type), + }, + when: JinjaWhenSourceArchiveUrl(type), + } +} + +export function AnsibleCreateVintnerDirectory() { + return { + name: 'create vintner directory', + 'ansible.builtin.file': { + path: '{{ SELF.application_directory }}/.vintner', + state: 'directory', + }, + } +} + +export function AnsibleCreateApplicationSystemdUnit() { + return { + name: 'create service', + 'ansible.builtin.copy': { + dest: '/etc/systemd/system/{{ SELF.application_name }}.service', + content: ApplicationSystemdUnit(), + }, + } +} + +export function AnsibleCreateApplicationEnvironment(type: NodeType) { + return { + name: 'create .env file', + 'ansible.builtin.copy': { + dest: '{{ SELF.application_directory }}/.env', + content: ApplicationEnvironment(type), + }, + } +} + +// TODO: support that operation is a path to a file, e.g., via artifact types ... (or even inline Ansible or Terraform) +export function AnsibleCopyManagementOperationTask(operation: MANAGEMENT_OPERATIONS) { + return { + name: 'copy management operation', + 'ansible.builtin.copy': { + dest: `{{ SELF.application_directory }}/.vintner/${operation}.sh`, + content: ManagementOperation(operation), + mode: '0755', + }, + when: JinjaWhenManagementOperationDefined(operation), + } +} + +export function AnsibleCallManagementOperationTask(operation: MANAGEMENT_OPERATIONS) { + return { + name: 'call management operation', + 'ansible.builtin.shell': `. .env && . .vintner/${operation}.sh`, + args: { + chdir: '{{ SELF.application_directory }}', + executable: '/bin/bash', + }, + when: JinjaWhenManagementOperationDefined(operation), + } +} + +export function AnsibleTouchComposeTask(options: {suffix: string}) { + return { + name: 'touch compose', + register: 'compose', + 'ansible.builtin.tempfile': { + suffix: `${options.suffix}.compose.yaml`, + }, + } +} + +export function AnsibleCreateComposeTask(options: {manifest: DockerCompose}) { + return { + name: 'create compose', + 'ansible.builtin.copy': { + dest: '{{ compose.path }}', + content: '{{ manifest | to_yaml }}', + }, + vars: { + manifest: options.manifest, + }, + } +} + +export function AnsibleApplyComposeTask() { + return { + name: 'unapply compose', + 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', + args: { + executable: '/usr/bin/bash', + }, + } +} + +export function AnsibleUnapplyComposeTask() { + return { + name: 'unapply compose', + 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} down', + args: { + executable: '/usr/bin/bash', + }, + } +} + +export function AnsibleTask(options: {task: AnsibleTaskOptions; module: string; options: any}) { + return { + ...options.task, + [options.module]: { + ...options.options, + }, + } +} + +/** + * https://docs.ansible.com/ansible/latest/collections/community/docker/docker_container_module.html + */ +export function AnsibleDockerContainerTask( + options: AnsibleTaskOptions & { + container: AnsibleModuleOptions & { + image?: string + command?: string + ports?: string[] + network_mode?: string + env?: {[key: string]: string} + } + } +) { + return AnsibleTask({ + task: options, + module: 'community.docker.docker_container', + options: options.container, + }) +} + +/** + * https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_db_module.html + */ +export function AnsibleMySQLDatabaseTask( + options: AnsibleTaskOptions & { + database: AnsibleModuleOptions & { + login_host: string + login_password: string + login_port: string + login_user: string + } + } +) { + return AnsibleTask({ + task: options, + module: 'community.mysql.mysql_db', + options: options.database, + }) +} + +/** + * https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_user_module.html + */ +export function AnsibleMySQLUserTask( + options: AnsibleTaskOptions & { + user: AnsibleModuleOptions & { + password: string + host: string + priv: string + login_host: string + login_password: string + login_port: string + login_user: string + } + } +) { + return AnsibleTask({ + task: options, + module: 'community.mysql.mysql_user', + options: options.user, + }) +} + +/** + * https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_module.html + */ +export function AnsibleAptTask( + options: AnsibleTaskOptions & { + apt: AnsibleModuleOptions & {} + } +) { + return AnsibleTask({ + task: options, + module: 'ansible.builtin.apt', + options: options.apt, + }) +} + +export function AnsibleAssertOperationTask(operation: MANAGEMENT_OPERATIONS) { + return { + name: 'assert management operation', + 'ansible.builtin.fail': { + dest: `Management operation "${operation}" missing`, + }, + when: JinjaWhenManagementOperationUndefined(operation), + } +} diff --git a/src/technologies/plugins/rules/utils/compose.ts b/src/technologies/plugins/rules/utils/compose.ts new file mode 100644 index 0000000000..bea37538ec --- /dev/null +++ b/src/technologies/plugins/rules/utils/compose.ts @@ -0,0 +1,12 @@ +export type DockerCompose = { + name?: string + services: { + [key: string]: { + container_name: string + image: string + network_mode: string + command?: string[] + environment?: {[key: string]: string} + } + } +} diff --git a/src/technologies/plugins/rules/utils/kubernetes.ts b/src/technologies/plugins/rules/utils/kubernetes.ts new file mode 100644 index 0000000000..a823f29951 --- /dev/null +++ b/src/technologies/plugins/rules/utils/kubernetes.ts @@ -0,0 +1,11 @@ +// TODO: continue this + +export type KubernetesDeploymentManifest = { + apiVersion: 'apps/v1' + kind: 'Deployment' + metadata: { + name: string + namespace: string + } & {[key: string]: string} + spec: any +} diff --git a/src/technologies/plugins/rules/utils/terraform.ts b/src/technologies/plugins/rules/utils/terraform.ts new file mode 100644 index 0000000000..75f25ad38d --- /dev/null +++ b/src/technologies/plugins/rules/utils/terraform.ts @@ -0,0 +1,104 @@ +export function TerraformRequiredVersion() { + return { + required_version: '>= 0.14.0', + } +} + +export function TerraformLocalProviderImport() { + return { + source: 'hashicorp/local', + version: '2.5.1', + } +} + +export function TerraformGoogleProviderImport() { + return { + source: 'hashicorp/google', + version: '4.67.0', + } +} + +export function TerraformGoogleProviderConfiguration() { + return { + credentials: '{{ SELF.gcp_service_account_file }}', + project: '{{ SELF.gcp_project }}', + region: '{{ SELF.gcp_region }}', + } +} + +export function TerraformKubernetesProviderImport() { + return { + source: 'hashicorp/kubernetes', + version: '2.31.0', + } +} + +export function TerraformDockerProviderImport() { + return { + source: 'kreuzwerker/docker', + version: '3.0.2', + } +} + +export function TerraformDockerProviderRemoteConfiguration() { + return { + host: 'ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22', + ssh_opts: [ + '-i', + '{{ SELF.os_ssh_key_file }}', + '-o', + 'IdentitiesOnly=yes', + '-o', + 'BatchMode=yes', + '-o', + 'UserKnownHostsFile=/dev/null', + '-o', + 'StrictHostKeyChecking=no', + ], + } +} + +export function TerraformDockerProviderLocalConfiguration() { + return { + host: 'unix:///var/run/docker.sock', + } +} + +export function TerraformKubernetesProviderConfiguration() { + return { + client_certificate: '${file("{{ SELF.k8s_client_cert_file }}")}', + client_key: '${file("{{ SELF.k8s_client_key_file }}")}', + cluster_ca_certificate: '${file("{{ SELF.k8s_ca_cert_file }}")}', + host: '{{ SELF.k8s_host }}', + } +} + +export function TerraformStandardOperations(env?: {[key: string]: any}) { + return { + Standard: { + operations: { + configure: { + implementation: { + primary: 'Terraform', + environment: env, + }, + }, + delete: { + implementation: { + primary: 'Terraform', + environment: env, + }, + }, + }, + }, + } +} + +export function TerraformSSHConnection() { + return { + host: '{{ SELF.os_ssh_host }}', + private_key: '${file("{{ SELF.os_ssh_key_file }}")}', + type: 'ssh', + user: '{{ SELF.os_ssh_user }}', + } +} diff --git a/src/technologies/plugins/rules/utils.ts b/src/technologies/plugins/rules/utils/utils.ts similarity index 55% rename from src/technologies/plugins/rules/utils.ts rename to src/technologies/plugins/rules/utils/utils.ts index 202d13321c..e0801a1465 100644 --- a/src/technologies/plugins/rules/utils.ts +++ b/src/technologies/plugins/rules/utils/utils.ts @@ -2,17 +2,12 @@ import * as assert from '#assert' import * as files from '#files' import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {NodeType, PropertyDefinition} from '#spec/node-type' +import {METADATA, PROPERTIES} from '#technologies/plugins/rules/types' import * as utils from '#utils' -import {UnexpectedError} from '#utils/error' -import {METADATA, PROPERTIES} from './types' // TODO: next: consider inherited types -export function mapProperties( - type: NodeType, - options: {quote?: boolean; format?: 'map' | 'list' | 'env'; ignore?: string[]} = {} -) { +export function ApplicationProperties(type: NodeType, options: {quote?: boolean; ignore?: string[]} = {}) { options.quote = options.quote ?? true - options.format = options.format ?? 'list' options.ignore = options.ignore ?? [] const list = Object.entries(type.properties || {}) @@ -36,13 +31,11 @@ export function mapProperties( }) .filter(it => !options.ignore!.includes(it.name)) - if (options.format === 'list') return list - - if (options.format === 'map') return utils.toMap(list) - - if (options.format === 'env') return files.toENV(utils.toMap(list), {quote: false}) - - throw new UnexpectedError() + return { + toList: () => list, + toMap: () => utils.toMap(list), + toEnv: () => files.toENV(utils.toMap(list), {quote: false}), + } } export function SecureApplicationProtocolPropertyDefinition(type: NodeType): {[key: string]: PropertyDefinition} { @@ -207,90 +200,6 @@ 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: { - type: 'unfurl.capabilities.Endpoint.Ansible', - properties: { - connection: 'ssh', - host: {eval: '.parent::management_address'}, - }, - }, - } -} - -export function AnsibleHostOperation() { - return { - primary: 'Ansible', - operation_host: 'HOST', - environment: { - ANSIBLE_HOST_KEY_CHECKING: 'False', - }, - } -} - -export function AnsibleOrchestratorOperation() { - return { - primary: 'Ansible', - operation_host: 'ORCHESTRATOR', - } -} - -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 }}'] -} - -export function AnsibleWaitForSSHTask() { - return { - name: 'wait for ssh', - wait_for_connection: null, - } -} - -export function TerraformStandardOperations(env?: {[key: string]: any}) { - return { - Standard: { - operations: { - configure: { - implementation: { - primary: 'Terraform', - environment: env, - }, - }, - delete: { - implementation: { - primary: 'Terraform', - environment: env, - }, - }, - }, - }, - } -} - export function ApplicationDirectory() { return { application_directory: { @@ -300,30 +209,10 @@ export function ApplicationDirectory() { } } -export function AnsibleCreateApplicationDirectoryTask() { - return { - name: 'create application directory', - 'ansible.builtin.file': { - path: '{{ SELF.application_directory }}', - state: 'directory', - }, - } -} - export function BashCreateApplicationDirectory() { return `mkdir -p {{ SELF.application_directory }}` } -export function AnsibleDeleteApplicationDirectoryTask() { - return { - name: 'delete application directory', - 'ansible.builtin.file': { - path: '{{ SELF.application_directory }}', - state: 'absent', - }, - } -} - export function BashDeleteApplicationDirectory() { return `rm -rf "{{ SELF.application_directory }}"` } @@ -336,18 +225,6 @@ export function SourceArchiveUrl(type: string) { return `{{ ".artifacts::${SourceArchiveName(type)}::file" | eval }}` } -export function AnsibleUnarchiveSourceArchiveFileTask(type: string) { - return { - name: 'extract deployment artifact in application directory', - 'ansible.builtin.unarchive': { - src: SourceArchiveFile(type), - dest: '{{ SELF.application_directory }}', - extra_opts: SourceArchiveExtraOpts(type), - }, - when: JinjaWhenSourceArchiveFile(type), - } -} - export function SourceArchiveExtraOpts(type: string) { return `{{ ".artifacts::${SourceArchiveName(type)}::extra_opts" | eval | map_value }}` } @@ -366,19 +243,6 @@ export function BashUnarchiveSourceArchiveFile(name: string, type: string) { } } -export function AnsibleUnarchiveSourceArchiveUrlTask(type: string) { - return { - name: 'extract deployment artifact from URL in application directory', - 'ansible.builtin.unarchive': { - src: SourceArchiveUrl(type), - dest: '{{ SELF.application_directory }}', - remote_src: 'yes', - extra_opts: SourceArchiveExtraOpts(type), - }, - when: JinjaWhenSourceArchiveUrl(type), - } -} - export function JinjaWhenSourceArchiveFile(type: string) { return `not (".artifacts::${SourceArchiveName(type)}::file" | eval).startswith("http")` } @@ -404,24 +268,12 @@ export function SourceArchiveName(type: string) { return type.replaceAll('.', '_') } -export function AnsibleCreateVintnerDirectory() { - return { - name: 'create vintner directory', - 'ansible.builtin.file': { - path: '{{ SELF.application_directory }}/.vintner', - state: 'directory', - }, - } -} - export function BashCreateVintnerDirectory() { return `mkdir -p {{ SELF.application_directory }}/.vintner` } export function ApplicationEnvironment(type: NodeType) { - const env = mapProperties(type, {format: 'env'}) - assert.isArray(env) - return env.join(`\n`) + return ApplicationProperties(type).toEnv().join(`\n`) } export function ApplicationSystemdUnit() { @@ -441,26 +293,6 @@ export function ApplicationSystemdUnit() { }) } -export function AnsibleCreateApplicationSystemdUnit() { - return { - name: 'create service', - 'ansible.builtin.copy': { - dest: '/etc/systemd/system/{{ SELF.application_name }}.service', - content: ApplicationSystemdUnit(), - }, - } -} - -export function AnsibleCreateApplicationEnvironment(type: NodeType) { - return { - name: 'create .env file', - 'ansible.builtin.copy': { - dest: '{{ SELF.application_directory }}/.env', - content: ApplicationEnvironment(type), - }, - } -} - export function BashCreateApplicationEnvironment(type: NodeType) { return ` cat < {{ SELF.application_directory }}/.env @@ -469,60 +301,25 @@ EOF>> `.trim() } -export function AnsibleAssertOperationTask(operation: MANAGEMENT_OPERATIONS) { - return { - name: 'assert management operation', - 'ansible.builtin.fail': { - dest: `Management operation "${operation}" missing`, - }, - when: JinjaWhenOperationUndefined(operation), - } -} - -export function BashAssertOperation(operation: MANAGEMENT_OPERATIONS) { +export function BashAssertManagementOperation(operation: MANAGEMENT_OPERATIONS) { return ` -if [[ ${BashWhenOperationUndefined(operation)} ]]; then +if [[ ${BashWhenManagementOperationUndefined(operation)} ]]; then echo 'Management operation "${operation}" missing' exit 1 fi `.trim() } -// TODO: support that operation is a path to a file, e.g., via artifact types ... (or even inline Ansible or Terraform) -export function AnsibleCopyOperationTask(operation: MANAGEMENT_OPERATIONS) { - return { - name: 'copy management operation', - 'ansible.builtin.copy': { - dest: `{{ SELF.application_directory }}/.vintner/${operation}.sh`, - content: Operation(operation), - mode: '0755', - }, - when: JinjaWhenOperationDefined(operation), - } -} - -export function AnsibleCallOperationTask(operation: MANAGEMENT_OPERATIONS) { - return { - name: 'call management operation', - 'ansible.builtin.shell': `. .env && . .vintner/${operation}.sh`, - args: { - chdir: '{{ SELF.application_directory }}', - executable: '/bin/bash', - }, - when: JinjaWhenOperationDefined(operation), - } -} - -export function BashCopyOperation(operation: MANAGEMENT_OPERATIONS) { +export function BashCopyManagementOperation(operation: MANAGEMENT_OPERATIONS) { return ` cat < {{ SELF.application_directory }}/.vintner/${operation}.sh -${Operation(operation)} +${ManagementOperation(operation)} EOF>> chmod +x {{ SELF.application_directory }}/.vintner/${operation}.sh `.trim() } -export function BashCallOperation(operation: MANAGEMENT_OPERATIONS) { +export function BashCallManagementOperation(operation: MANAGEMENT_OPERATIONS) { return ` cd {{ SELF.application_directory }} . .env @@ -530,32 +327,36 @@ cd {{ SELF.application_directory }} `.trim() } -export function Operation(operation: MANAGEMENT_OPERATIONS) { +export function ManagementOperation(operation: MANAGEMENT_OPERATIONS) { return `${BASH_HEADER} -{{ (${SelfOperation(operation)} == "${VINTNER_MANAGEMENT_OPERATION_UNDEFINED}" ) | ternary("echo 0", ${SelfOperation( +{{ (${SelfManagementOperation( operation - )}) }} + )} == "${VINTNER_MANAGEMENT_OPERATION_UNDEFINED}" ) | ternary("echo 0", ${SelfManagementOperation(operation)}) }} `.trim() } -export function JinjaWhenOperationDefined(operation: MANAGEMENT_OPERATIONS) { - return `${SelfOperation(operation)} != "${VINTNER_MANAGEMENT_OPERATION_UNDEFINED}"` +export function JinjaWhenManagementOperationDefined(operation: MANAGEMENT_OPERATIONS) { + return `${SelfManagementOperation(operation)} != "${VINTNER_MANAGEMENT_OPERATION_UNDEFINED}"` } -export function JinjaWhenOperationUndefined(operation: MANAGEMENT_OPERATIONS) { - return `${SelfOperation(operation)} == "${VINTNER_MANAGEMENT_OPERATION_UNDEFINED}"` +export function JinjaWhenManagementOperationUndefined(operation: MANAGEMENT_OPERATIONS) { + return `${SelfManagementOperation(operation)} == "${VINTNER_MANAGEMENT_OPERATION_UNDEFINED}"` } -export function BashWhenOperationDefined(operation: MANAGEMENT_OPERATIONS) { - return `"{{ ${SelfOperation(operation)} | split('\\n') | first }}" != "${VINTNER_MANAGEMENT_OPERATION_UNDEFINED}"` +export function BashWhenManagementOperationDefined(operation: MANAGEMENT_OPERATIONS) { + return `"{{ ${SelfManagementOperation( + operation + )} | split('\\n') | first }}" != "${VINTNER_MANAGEMENT_OPERATION_UNDEFINED}"` } -export function BashWhenOperationUndefined(operation: MANAGEMENT_OPERATIONS) { - return `"{{ ${SelfOperation(operation)} | split('\\n') | first }}" == "${VINTNER_MANAGEMENT_OPERATION_UNDEFINED}"` +export function BashWhenManagementOperationUndefined(operation: MANAGEMENT_OPERATIONS) { + return `"{{ ${SelfManagementOperation( + operation + )} | split('\\n') | first }}" == "${VINTNER_MANAGEMENT_OPERATION_UNDEFINED}"` } -export function SelfOperation(operation: MANAGEMENT_OPERATIONS) { +export function SelfManagementOperation(operation: MANAGEMENT_OPERATIONS) { return `SELF._management_${operation}` } @@ -565,3 +366,5 @@ set -e `.trim() export const VINTNER_MANAGEMENT_OPERATION_UNDEFINED = 'VINTNER_MANAGEMENT_OPERATION_UNDEFINED' + +export const LOCALHOST = '127.0.0.1' From 9171d2629c656f59a6af08bccf635faeb5b704d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Sat, 7 Sep 2024 22:54:55 +0200 Subject: [PATCH 07/18] fixes --- .../lib/shop.component.yaml | 182 +- .../lib/technology-rules.yaml | 232 + .../lib/tosca-vintner-profile-core.yaml | 1626 ++- .../lib/tosca-vintner-profile-extended.yaml | 11519 ++++++++++++---- .../remote-machine/compose/index.ts | 2 +- .../plugins/rules/utils/ansible.ts | 6 +- 6 files changed, 10675 insertions(+), 2892 deletions(-) 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 a091e1f46a..3f2ede1f59 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 @@ -75,6 +75,186 @@ node_types: # ################################################################ + shop.component~service.application#docker.image::ansible@docker.engine->local.machine: + derived_from: shop.component + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: + 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 }}"' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + shop.component~service.application#docker.image::compose@docker.engine->local.machine: + derived_from: shop.component + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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: unapply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + shop.component~service.application#docker.image::terraform@docker.engine->local.machine: + derived_from: shop.component + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + required_version: '>= 0.14.0' + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: + - 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 }} + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' shop.component~service.application#docker.image::ansible@docker.engine->remote.machine: derived_from: shop.component metadata: @@ -234,7 +414,7 @@ node_types: DB_PORT: '"{{ SELF.DB_PORT }}"' FEATURE_OPTIONAL: '"{{ SELF.optional_feature }}"' FEATURE_PREMIUM: '"{{ SELF.premium_feature }}"' - - name: apply compose + - name: unapply compose ansible.builtin.shell: docker compose -f {{ compose.path }} down args: executable: /usr/bin/bash diff --git a/examples/unfurl-technology---shop---plus-maintenance-automated/lib/technology-rules.yaml b/examples/unfurl-technology---shop---plus-maintenance-automated/lib/technology-rules.yaml index 527f8fd3c3..bd593ee0f0 100644 --- a/examples/unfurl-technology---shop---plus-maintenance-automated/lib/technology-rules.yaml +++ b/examples/unfurl-technology---shop---plus-maintenance-automated/lib/technology-rules.yaml @@ -4,6 +4,78 @@ # ################################################### +- technology: ansible + component: bucket + hosting: + - gcp.cloudstorage + weight: 0.5 + reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. +- technology: terraform + component: bucket + hosting: + - gcp.cloudstorage + weight: 1 + reason: Terraform provides a declarative module. +- technology: ansible + component: bucket + hosting: + - minio.server + - '*' + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. +- technology: terraform + component: bucket + hosting: + - minio.server + - '*' + - local.machine + weight: 1 + reason: Terraform provides a declarative module. +- technology: ansible + component: bucket + hosting: + - minio.server + - '*' + - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. +- technology: terraform + component: bucket + hosting: + - minio.server + - '*' + - remote.machine + weight: 1 + reason: Terraform provides a declarative module. +- technology: ansible + component: bucket + hosting: + - minio.server + - kubernetes.cluster + weight: 1 + reason: Primary use case due to the specialization of Ansible. +- technology: terraform + component: bucket + hosting: + - minio.server + - kubernetes.cluster + weight: 1 + reason: Terraform provides a declarative module. +- technology: ansible + component: docker.engine + hosting: + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks' +- technology: terraform + component: docker.engine + hosting: + - local.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"local-exec" provider' - technology: ansible component: docker.engine hosting: @@ -65,6 +137,30 @@ weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' +- technology: ansible + component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. +- technology: compose + component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - local.machine + weight: 0 + reason: One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. +- technology: terraform + component: mysql.database + hosting: + - mysql.dbms + - docker.engine + - local.machine + weight: 0.5 + reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. - technology: ansible component: mysql.database hosting: @@ -138,6 +234,33 @@ - remote.machine weight: 0.5 reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. +- technology: ansible + component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized + details: '"community.docker.docker_container" task' +- technology: compose + component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - local.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker-compose manifest generated and applied +- technology: terraform + component: mysql.dbms + artifact: dbms.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' - technology: ansible component: mysql.dbms artifact: dbms.image @@ -221,6 +344,115 @@ weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' +- technology: ansible + component: bucket + artifact: cache.image + hosting: + - gcp.memorystore + weight: 0.5 + reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. +- technology: terraform + component: redis.server + artifact: cache.image + hosting: + - gcp.memorystore + weight: 1 + reason: Terraform provides a declarative module. +- technology: ansible + component: redis.server + artifact: cache.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"community.docker.docker_container" task' +- technology: compose + component: redis.server + artifact: cache.image + hosting: + - docker.engine + - local.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker compose manifest generated and applied +- technology: terraform + component: redis.server + artifact: cache.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' +- technology: ansible + component: redis.server + artifact: cache.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"community.docker.docker_container" task' +- technology: compose + component: redis.server + artifact: cache.image + hosting: + - docker.engine + - remote.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker compose manifest generated and applied +- technology: terraform + component: redis.server + artifact: cache.image + hosting: + - docker.engine + - remote.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' +- technology: ansible + component: redis.server + artifact: cache.image + hosting: + - kubernetes.cluster + weight: 1 + reason: Primary use case due to the specialization of Ansible. +- technology: terraform + component: redis.server + artifact: cache.image + hosting: + - kubernetes.cluster + weight: 1 + reason: Terraform provides a declarative module. +- technology: ansible + component: service.application + artifact: docker.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"community.docker.docker_container" task' +- technology: compose + component: service.application + artifact: docker.image + hosting: + - docker.engine + - local.machine + weight: 1 + reason: Docker is the underlying technology. + details: docker compose manifest generated and applied +- technology: terraform + component: service.application + artifact: docker.image + hosting: + - docker.engine + - local.machine + weight: 0.5 + reason: Docker Compose is more specialized. + details: '"docker_container" and "docker_image" resources' - technology: ansible component: service.application artifact: docker.image 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 bcadd5c029..eb2789c44f 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 @@ -72,6 +72,9 @@ artifact_types: dbms.image: derived_from: artifact description: expects image reference in "file" + cache.image: + derived_from: artifact + description: expects image reference in "file" interface_types: interface: derived_from: tosca.interfaces.Root @@ -230,10 +233,16 @@ node_types: properties: machine_name: type: string + attributes: + application_address: + type: string + management_address: + type: string local.machine: derived_from: machine metadata: vintner_normative: 'true' + vintner_abstract: 'true' capabilities: host: type: tosca.capabilities.Compute @@ -259,13 +268,6 @@ node_types: type: string ssh_key_file: type: string - attributes: - management_address: - type: string - application_address: - type: string - default: - eval: .::management_address capabilities: host: type: tosca.capabilities.Compute @@ -275,6 +277,10 @@ node_types: connection: ssh host: eval: .parent::management_address + attributes: + application_address: + default: + eval: .::management_address virtual.machine: derived_from: remote.machine physical.machine: @@ -284,6 +290,10 @@ node_types: metadata: vintner_normative: 'true' vintner_abstract: 'true' + requirements: + - host: + capability: tosca.capabilities.Compute + relationship: tosca.relationships.HostedOn relational.database: derived_from: database metadata: @@ -299,6 +309,34 @@ node_types: metadata: vintner_normative: 'true' vintner_abstract: 'true' + cache: + derived_from: software.application + storage: + derived_from: node + block.storage: + derived_from: storage + object.storage: + derived_from: storage + file.storage: + derived_from: storage + bucket: + derived_from: object.storage + metadata: + vintner_normative: 'true' + properties: + bucket_name: + type: string + bucket_dialect: + type: string + attributes: + bucket_endpoint: + type: string + bucket_token: + type: string + requirements: + - host: + capability: tosca.capabilities.Compute + relationship: tosca.relationships.HostedOn ingress: derived_from: node metadata: @@ -549,6 +587,1580 @@ node_types: openstack_networking_secgroup_v2: ports: - name: '{{ SELF.machine_name }}' + cache~software.application#apt.package::ansible@*->remote.machine: + derived_from: cache + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + cache~software.application#apt.archive::terraform@*->remote.machine: + derived_from: cache + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-cache {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-cache.sh + remote-exec: + - inline: + - sudo bash /tmp/create-cache.sh + - sudo bash /tmp/configure-cache.sh + - sudo bash /tmp/start-cache.sh + - inline: + - sudo bash /tmp/stop-cache.sh + - sudo bash /tmp/delete-cache.sh + when: destroy + cache~software.application#tar.archive::ansible@*->remote.machine: + derived_from: cache + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + cache~software.application#tar.archive::terraform@*->remote.machine: + derived_from: cache + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-cache + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-cache {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-cache -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-cache.sh + remote-exec: + - inline: + - sudo bash /tmp/create-cache.sh + - sudo bash /tmp/configure-cache.sh + - sudo bash /tmp/start-cache.sh + - inline: + - sudo bash /tmp/stop-cache.sh + - sudo bash /tmp/delete-cache.sh + when: destroy + cache~software.application#zip.archive::ansible@*->remote.machine: + derived_from: cache + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + cache~software.application#zip.archive::terraform@*->remote.machine: + derived_from: cache + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-cache + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-cache {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-cache -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-cache.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-cache.sh + remote-exec: + - inline: + - sudo bash /tmp/create-cache.sh + - sudo bash /tmp/configure-cache.sh + - sudo bash /tmp/start-cache.sh + - inline: + - sudo bash /tmp/stop-cache.sh + - sudo bash /tmp/delete-cache.sh + when: destroy + bucket~bucket::ansible@gcp.cloudstorage: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: [] + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: [] + bucket~bucket::terraform@gcp.cloudstorage: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + delete: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + mysql: + source: petoju/mysql + version: 3.0.48 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + resource: {} + bucket~bucket::ansible@minio.server->*->local.machine: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + bucket~bucket::terraform@minio.server->*->local.machine: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: [] + provider: {} + resource: {} + bucket~bucket::ansible@minio.server->*->remote.machine: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + bucket~bucket::terraform@minio.server->*->remote.machine: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + delete: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + defaults: + inputs: + main: + terraform: [] + provider: {} + resource: {} + bucket~bucket::ansible@minio.server->kubernetes.cluster: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + bucket~bucket::terraform@minio.server->kubernetes.cluster: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + delete: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + defaults: + inputs: + main: + terraform: [] + provider: {} + resource: {} + bucket~bucket#cache.image::ansible@gcp.memorystore: + derived_from: bucket + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: [] + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: [] ingress~ingress::ansible@kubernetes.cluster: derived_from: ingress metadata: 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 3750f5c5ea..0e4edf7f26 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 @@ -99,6 +99,15 @@ node_types: operations: configure: npm ci start: npm start + reactjs.service.application: + derived_from: service.application + metadata: + vintner_normative: 'true' + vintner_abstract: 'true' + properties: + application_language: + type: string + default: nodejs18 python.runtime: derived_from: software.runtime metadata: @@ -312,6 +321,30 @@ node_types: gcp_service: type: string default: cloudbuild.googleapis.com + gcp.kubernetesengine: + derived_from: gcp.service + metadata: + vintner_normative: 'true' + properties: + gcp_service: + type: string + default: container.googleapis.com + gcp.cloudstorage: + derived_from: gcp.service + metadata: + vintner_normative: 'true' + properties: + gcp_service: + type: string + default: storage.googleapis.com + gcp.memorystore: + derived_from: gcp.service + metadata: + vintner_normative: 'true' + properties: + gcp_service: + type: string + default: redis.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 @@ -450,6 +483,28 @@ node_types: - host: capability: tosca.capabilities.Compute relationship: tosca.relationships.HostedOn + minio.server: + derived_from: service.application + metadata: + vintner_normative: 'true' + redis.server: + derived_from: cache + metadata: + vintner_normative: 'true' + properties: + cache_name: + type: string + cache_port: + type: string + application_protocol: + type: string + default: redis + application_name: + default: + eval: .::cache_name + application_port: + default: + eval: .::cache_port # [OPENTOSCA_VINTNER_GENERATION_MARK] @@ -5419,6 +5474,7 @@ node_types: - google: source: hashicorp/google version: 4.67.0 + required_version: '>= 0.14.0' provider: google: - credentials: '{{ SELF.gcp_service_account_file }}' @@ -5502,6 +5558,7 @@ node_types: - google: source: hashicorp/google version: 4.67.0 + required_version: '>= 0.14.0' provider: google: - credentials: '{{ SELF.gcp_service_account_file }}' @@ -5585,6 +5642,7 @@ node_types: - google: source: hashicorp/google version: 4.67.0 + required_version: '>= 0.14.0' provider: google: - credentials: '{{ SELF.gcp_service_account_file }}' @@ -5668,6 +5726,7 @@ node_types: - google: source: hashicorp/google version: 4.67.0 + required_version: '>= 0.14.0' provider: google: - credentials: '{{ SELF.gcp_service_account_file }}' @@ -5751,6 +5810,7 @@ node_types: - google: source: hashicorp/google version: 4.67.0 + required_version: '>= 0.14.0' provider: google: - credentials: '{{ SELF.gcp_service_account_file }}' @@ -5762,141 +5822,61 @@ node_types: - disable_on_destroy: false project: '{{ SELF.gcp_project }}' service: '{{ SELF.gcp_service }}' - docker.engine~docker.engine::ansible@remote.machine: - derived_from: docker.engine + gcp.kubernetesengine~gcp.service::ansible: + derived_from: gcp.kubernetesengine metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: + gcp_service_account_file: type: string default: - get_input: os_ssh_user - os_ssh_key_file: + get_input: gcp_service_account_file + gcp_region: type: string default: - get_input: os_ssh_key_file + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project interfaces: Standard: operations: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install docker - 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 - - name: add user to docker group - ansible.builtin.user: - name: '{{ SELF.os_ssh_user }}' - groups: docker - append: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST + operation_host: ORCHESTRATOR environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount 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~docker.engine::terraform@remote.machine: - derived_from: docker.engine + - name: enable service + google.cloud.gcp_serviceusage_service: + name: '{{ SELF.gcp_service }}' + project: '{{ SELF.gcp_project }}' + delete: exit 0 + gcp.kubernetesengine~gcp.service::terraform: + derived_from: gcp.kubernetesengine metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: + gcp_service_account_file: type: string default: - get_input: os_ssh_user - os_ssh_key_file: + get_input: gcp_service_account_file + gcp_region: type: string default: - get_input: os_ssh_key_file - os_ssh_host: + get_input: gcp_region + gcp_project: type: string default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 + get_input: gcp_project interfaces: Standard: operations: @@ -5909,325 +5889,78 @@ node_types: defaults: inputs: main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 4.67.0 + required_version: '>= 0.14.0' + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' resource: - terraform_data: - docker: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - 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.package::ansible@*->remote.machine: - derived_from: docker.engine + google_project_service: + cloud_sql_admin: + - disable_on_destroy: false + project: '{{ SELF.gcp_project }}' + service: '{{ SELF.gcp_service }}' + gcp.cloudstorage~gcp.service::ansible: + derived_from: gcp.cloudstorage metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: + gcp_service_account_file: type: string default: - get_input: os_ssh_user - os_ssh_key_file: + get_input: gcp_service_account_file + gcp_region: type: string default: - get_input: os_ssh_key_file - application_directory: + get_input: gcp_region + gcp_project: type: string default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name + get_input: gcp_project interfaces: Standard: operations: create: implementation: primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST + operation_host: ORCHESTRATOR environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - docker.engine~software.application#apt.archive::terraform@*->remote.machine: - derived_from: docker.engine + - name: enable service + google.cloud.gcp_serviceusage_service: + name: '{{ SELF.gcp_service }}' + project: '{{ SELF.gcp_project }}' + delete: exit 0 + gcp.cloudstorage~gcp.service::terraform: + derived_from: gcp.cloudstorage metadata: vintner_generated: 'true' + vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + gcp_service_account_file: type: string default: - get_input: os_ssh_key_file - os_ssh_host: + get_input: gcp_service_account_file + gcp_region: type: string default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: + get_input: gcp_region + gcp_project: type: string default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name + get_input: gcp_project interfaces: Standard: operations: @@ -6240,411 +5973,208 @@ node_types: defaults: inputs: main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 4.67.0 + required_version: '>= 0.14.0' + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - _HOSTING="{{ SELF._hosting }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-docker.engine {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-docker.engine.sh - remote-exec: - - inline: - - sudo bash /tmp/create-docker.engine.sh - - sudo bash /tmp/configure-docker.engine.sh - - sudo bash /tmp/start-docker.engine.sh - - inline: - - sudo bash /tmp/stop-docker.engine.sh - - sudo bash /tmp/delete-docker.engine.sh - when: destroy - docker.engine~software.application#tar.archive::ansible@*->remote.machine: - derived_from: docker.engine + google_project_service: + cloud_sql_admin: + - disable_on_destroy: false + project: '{{ SELF.gcp_project }}' + service: '{{ SELF.gcp_service }}' + gcp.memorystore~gcp.service::ansible: + derived_from: gcp.memorystore metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: + gcp_service_account_file: type: string default: - get_input: os_ssh_user - os_ssh_key_file: + get_input: gcp_service_account_file + gcp_region: type: string default: - get_input: os_ssh_key_file - application_directory: + get_input: gcp_region + gcp_project: type: string default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name + get_input: gcp_project interfaces: Standard: operations: create: implementation: primary: Ansible - operation_host: HOST + operation_host: ORCHESTRATOR environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount inputs: playbook: q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: |- - APPLICATION_NAME="{{ SELF.application_name }}" - _HOSTING="{{ SELF._hosting }}" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' + - name: enable service + google.cloud.gcp_serviceusage_service: + name: '{{ SELF.gcp_service }}' + project: '{{ SELF.gcp_project }}' + delete: exit 0 + gcp.memorystore~gcp.service::terraform: + derived_from: gcp.memorystore + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: configure: implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: + primary: Terraform + delete: implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 4.67.0 + required_version: '>= 0.14.0' + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + resource: + google_project_service: + cloud_sql_admin: + - disable_on_destroy: false + project: '{{ SELF.gcp_project }}' + service: '{{ SELF.gcp_service }}' + docker.engine~docker.engine::ansible@local.machine: + derived_from: docker.engine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + 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: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation + - name: install docker + ansible.builtin.shell: curl -sSL https://get.docker.com | sh + args: + executable: /usr/bin/bash + - name: update service ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e + 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 - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' + [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 + - name: add user to docker group + ansible.builtin.user: + name: '{{ SELF.os_ssh_user }}' + groups: docker + append: 'yes' delete: 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: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory + - 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: - path: '{{ SELF.application_directory }}' + name: '{{ item }}' state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - docker.engine~software.application#tar.archive::terraform@*->remote.machine: + loop: + - /var/lib/docker + - /var/lib/containerd + docker.engine~docker.engine::terraform@local.machine: derived_from: docker.engine metadata: vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: + vintner_orchestrator: unfurl + attributes: + application_address: type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name + default: 127.0.0.1 interfaces: Standard: operations: @@ -6657,154 +6187,66 @@ node_types: defaults: inputs: main: + terraform: + - required_providers: + - mysql: + source: hashicorp/local + version: 2.5.1 + required_version: '>= 0.14.0' + provider: + local: + - endpoint: 127.0.0.1:{{ HOST.management_port }} + password: '{{ HOST.dbms_password }}' + username: root resource: + local_file: + tmp_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 + filename: /tmp/docker.service terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' + docker: + - depends_on: local_file.tmp_service provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-docker.engine - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - _HOSTING="{{ SELF._hosting }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-docker.engine {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-docker.engine -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-docker.engine.sh - remote-exec: + local-exec: - inline: - - sudo bash /tmp/create-docker.engine.sh - - sudo bash /tmp/configure-docker.engine.sh - - sudo bash /tmp/start-docker.engine.sh + - 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 bash /tmp/stop-docker.engine.sh - - sudo bash /tmp/delete-docker.engine.sh + - 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#zip.archive::ansible@*->remote.machine: + docker.engine~docker.engine::ansible@remote.machine: derived_from: docker.engine metadata: vintner_generated: 'true' @@ -6818,14 +6260,6 @@ node_types: type: string default: get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name interfaces: Standard: operations: @@ -6840,57 +6274,58 @@ node_types: q: - name: wait for ssh wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: |- - APPLICATION_NAME="{{ SELF.application_name }}" - _HOSTING="{{ SELF._hosting }}" - - name: copy management operation + - name: install docker + ansible.builtin.shell: curl -sSL https://get.docker.com | sh + args: + executable: /usr/bin/bash + - name: update service ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e + 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 - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + [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 + - name: add user to docker group + ansible.builtin.user: + name: '{{ SELF.os_ssh_user }}' + groups: docker + append: 'yes' playbookArgs: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - configure: + delete: implementation: primary: Ansible operation_host: HOST @@ -6901,24 +6336,235 @@ node_types: q: - name: wait for ssh wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' + - 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~docker.engine::terraform@remote.machine: + derived_from: docker.engine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_version: '>= 0.14.0' + resource: + terraform_data: + docker: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + 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 + 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 + 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.package::ansible@*->remote.machine: + derived_from: docker.engine + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' start: @@ -6932,10 +6578,6 @@ node_types: q: - name: wait for ssh wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - name: copy management operation ansible.builtin.copy: dest: '{{ SELF.application_directory }}/.vintner/start.sh' @@ -6967,10 +6609,6 @@ node_types: q: - name: wait for ssh wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - name: copy management operation ansible.builtin.copy: dest: '{{ SELF.application_directory }}/.vintner/stop.sh' @@ -7022,11 +6660,15 @@ node_types: ansible.builtin.file: path: '{{ SELF.application_directory }}' state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent playbookArgs: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - docker.engine~software.application#zip.archive::terraform@*->remote.machine: + docker.engine~software.application#apt.archive::terraform@*->remote.machine: derived_from: docker.engine metadata: vintner_generated: 'true' @@ -7073,29 +6715,52 @@ node_types: user: '{{ SELF.os_ssh_user }}' provisioner: file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-docker.engine - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - content: | #!/usr/bin/bash set -e - # Create application directory - mkdir -p {{ SELF.application_directory }} + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - _HOSTING="{{ SELF._hosting }}" - EOF>> + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + _HOSTING="{{ SELF._hosting }}" + EOF>> # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-docker.engine {{ ".artifacts::zip_archive::file" | eval }} + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-docker.engine {{ ".artifacts::apt_archive::file" | eval }} fi # Extract deployment artifact - unzip /tmp/artifact-docker.engine -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + undefined # Create vintner directory mkdir -p {{ SELF.application_directory }}/.vintner @@ -7136,12 +6801,6 @@ node_types: #!/usr/bin/bash set -e - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - # Copy operation cat < {{ SELF.application_directory }}/.vintner/start.sh #!/usr/bin/bash @@ -7160,12 +6819,6 @@ node_types: #!/usr/bin/bash set -e - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - # Copy operation cat < {{ SELF.application_directory }}/.vintner/stop.sh #!/usr/bin/bash @@ -7200,6 +6853,9 @@ node_types: # Delete application directory rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y destination: /tmp/delete-docker.engine.sh remote-exec: - inline: @@ -7210,8 +6866,8 @@ node_types: - sudo bash /tmp/stop-docker.engine.sh - sudo bash /tmp/delete-docker.engine.sh when: destroy - mysql.dbms~mysql.dbms#dbms.image::ansible@docker.engine->remote.machine: - derived_from: mysql.dbms + docker.engine~software.application#tar.archive::ansible@*->remote.machine: + derived_from: docker.engine metadata: vintner_generated: 'true' vintner_orchestrator: unfurl @@ -7224,20 +6880,14 @@ node_types: type: string default: get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: 127.0.0.1 - application_port: - type: string - default: 3306 - management_address: + application_directory: type: string default: - eval: .::.requirements::[.name=host]::.target::management_address - management_port: - type: integer - default: 3306 + concat: + - /var/lib/ + - get_property: + - SELF + - application_name interfaces: Standard: operations: @@ -7252,18 +6902,54 @@ node_types: q: - name: wait for ssh wait_for_connection: - - name: start container - community.docker.docker_container: - name: '{{ SELF.dbms_name }}' - image: mysql:{{ ".artifacts::dbms_image::file" | eval }} - network_mode: host - env: - MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password | string }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: |- + APPLICATION_NAME="{{ SELF.application_name }}" + _HOSTING="{{ SELF._hosting }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" playbookArgs: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: + configure: implementation: primary: Ansible operation_host: HOST @@ -7274,118 +6960,135 @@ node_types: q: - name: wait for ssh wait_for_connection: - - name: delete container - community.docker.docker_container: - name: '{{ SELF.dbms_name }}' - state: absent + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" playbookArgs: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - 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_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - application_port: - type: integer - default: 3306 - management_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - management_port: - type: integer - default: 3306 - capabilities: - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address - interfaces: - Standard: - operations: - create: + start: implementation: primary: Ansible - operation_host: ORCHESTRATOR + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' inputs: playbook: q: - - name: touch compose - register: compose - ansible.builtin.tempfile: - suffix: '{{ SELF.dbms_name }}.compose.yaml' - - name: create compose + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation 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: apply compose - ansible.builtin.shell: docker compose -f {{ compose.path }} up -d + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh args: - executable: /usr/bin/bash - environment: - DOCKER_HOST: '{{ SELF.os_ssh_host }}' - - name: let it cook - ansible.builtin.pause: - seconds: 10 - delete: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: implementation: primary: Ansible - operation_host: ORCHESTRATOR + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' inputs: playbook: q: - - name: touch compose - register: compose - ansible.builtin.tempfile: - suffix: '{{ SELF.dbms_name }}.compose.yaml' - - name: create compose + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation 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 + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh args: - executable: /usr/bin/bash - environment: - DOCKER_HOST: '{{ SELF.os_ssh_host }}' - mysql.dbms~mysql.dbms#dbms.image::terraform@docker.engine->remote.machine: - derived_from: mysql.dbms + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + docker.engine~software.application#tar.archive::terraform@*->remote.machine: + derived_from: docker.engine metadata: vintner_generated: 'true' - vintner_orchestrator: unfurl properties: os_ssh_user: type: string @@ -7399,27 +7102,14 @@ node_types: type: string default: eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - application_port: - type: integer - default: 3306 - management_address: + application_directory: type: string default: - eval: .::.requirements::[.name=host]::.target::management_address - management_port: - type: integer - default: 3306 - capabilities: - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address + concat: + - /var/lib/ + - get_property: + - SELF + - application_name interfaces: Standard: operations: @@ -7432,382 +7122,632 @@ node_types: defaults: inputs: main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 - ssh_opts: - - '-i' - - '{{ SELF.os_ssh_key_file }}' - - '-o' - - IdentitiesOnly=yes - - '-o' - - BatchMode=yes - - '-o' - - UserKnownHostsFile=/dev/null - - '-o' - - StrictHostKeyChecking=no resource: - docker_container: - application: - - name: '{{ SELF.dbms_name }}' - image: ${docker_image.image.image_id} - network_mode: host - env: - - MYSQL_ROOT_PASSWORD={{ SELF.dbms_password }} - docker_image: - image: - - name: mysql:{{ ".artifacts::dbms_image::file" | eval }} - mysql.dbms~mysql.dbms#dbms.image::ansible@gcp.cloudsql: - derived_from: mysql.dbms - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - dbms_ssl_mode: - type: string - default: Preferred - attributes: - application_port: - type: string - default: 3306 - management_address: - type: string - default: - eval: .::application_address - management_port: - type: integer - default: - eval: .::application_port - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: - - name: create a instance - register: instance_info - google.cloud.gcp_sql_instance: - name: '{{ SELF.dbms_name }}' - database_version: MYSQL_{{ ".artifacts::dbms_image::file" | eval | replace(".", "_") }} - settings: - tier: db-f1-micro - availability_type: REGIONAL - backup_configuration: - binary_log_enabled: true - enabled: true - ip_configuration: - authorized_networks: - - value: 0.0.0.0/0 - region: '{{ SELF.gcp_region }}' - project: '{{ SELF.gcp_project }}' - - name: set root password - google.cloud.gcp_sql_user: - name: root - host: '%' - password: '{{ SELF.dbms_password }}' - instance: '{{ instance_info }}' - project: '{{ SELF.gcp_project }}' - - name: aet attributes - set_fact: - application_address: '{{ instance_info.ipAddresses[0].ipAddress | trim }}' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address }}' - outputs: - application_address: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: Activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: Delete Instance - ansible.builtin.shell: gcloud sql instances delete {{ SELF.dbms_name }} --quiet - args: - executable: /bin/bash - mysql.dbms~mysql.dbms#dbms.image::terraform@gcp.cloudsql: - derived_from: mysql.dbms - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - dbms_ssl_mode: - type: string - default: Preferred - attributes: - application_port: - type: string - default: 3306 - management_address: - type: string - default: - eval: .::application_address - management_port: - type: integer - default: - eval: .::application_port - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 4.67.0 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: ${google_sql_database_instance.dbms.public_ip_address} - resource: - google_sql_database_instance: - dbms: - - database_version: MYSQL_{{ ".artifacts::dbms_image::file" | eval | replace(".", "_") }} - deletion_protection: false - name: '{{ SELF.dbms_name }}' - root_password: '{{ SELF.dbms_password }}' - settings: - - availability_type: REGIONAL - backup_configuration: - - binary_log_enabled: true - enabled: true - ip_configuration: - - authorized_networks: - - name: public - value: 0.0.0.0/0 - ipv4_enabled: true - tier: db-f1-micro - google_sql_user: - user: - - host: '%' - instance: ${google_sql_database_instance.dbms.name} - name: root - password: ${google_sql_database_instance.dbms.root_password} - mysql.dbms~mysql.dbms#dbms.image::ansible@kubernetes.cluster: - derived_from: mysql.dbms + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-docker.engine + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + _HOSTING="{{ SELF._hosting }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-docker.engine {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-docker.engine -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-docker.engine.sh + remote-exec: + - inline: + - sudo bash /tmp/create-docker.engine.sh + - sudo bash /tmp/configure-docker.engine.sh + - sudo bash /tmp/start-docker.engine.sh + - inline: + - sudo bash /tmp/stop-docker.engine.sh + - sudo bash /tmp/delete-docker.engine.sh + when: destroy + docker.engine~software.application#zip.archive::ansible@*->remote.machine: + derived_from: docker.engine metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: + os_ssh_user: type: string default: - get_input: k8s_client_key_file - attributes: - application_address: + get_input: os_ssh_user + os_ssh_key_file: type: string default: - eval: .::dbms_name - application_port: - type: integer - default: 3306 - management_address: + get_input: os_ssh_key_file + application_directory: type: string default: - eval: .::application_address - management_port: - type: integer - default: - eval: .::application_port + concat: + - /var/lib/ + - get_property: + - SELF + - application_name interfaces: Standard: operations: create: implementation: primary: Ansible - operation_host: ORCHESTRATOR + operation_host: HOST 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 + ANSIBLE_HOST_KEY_CHECKING: 'False' inputs: playbook: q: - - name: create deployment - kubernetes.core.k8s: - wait: true - definition: - 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 - - name: create service - kubernetes.core.k8s: - definition: - apiVersion: v1 - kind: Service - metadata: - name: '{{ SELF.dbms_name }}' - namespace: default - spec: - ports: - - name: mysql - port: 3306 - targetPort: 3306 - selector: - app: '{{ SELF.dbms_name }}' - type: ClusterIP + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: |- + APPLICATION_NAME="{{ SELF.application_name }}" + _HOSTING="{{ SELF._hosting }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' delete: implementation: primary: Ansible - operation_host: ORCHESTRATOR + operation_host: HOST 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 + ANSIBLE_HOST_KEY_CHECKING: 'False' 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: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' state: absent - api_version: apps/v1 - kind: Deployment - name: '{{ SELF.dbms_name }}' - namespace: default - mysql.dbms~mysql.dbms#dbms.image::kubernetes@kubernetes.cluster: - derived_from: mysql.dbms + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + docker.engine~software.application#zip.archive::terraform@*->remote.machine: + derived_from: docker.engine metadata: vintner_generated: 'true' - vintner_orchestrator: unfurl properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: + os_ssh_user: type: string default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: + get_input: os_ssh_user + os_ssh_key_file: type: string default: - get_input: k8s_client_cert_file - k8s_client_key_file: + get_input: os_ssh_key_file + os_ssh_host: type: string default: - get_input: k8s_client_key_file - attributes: - application_address: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: type: string default: - eval: .::dbms_name + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-docker.engine + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + APPLICATION_NAME="{{ SELF.application_name }}" + _HOSTING="{{ SELF._hosting }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-docker.engine {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-docker.engine -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-docker.engine.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-docker.engine.sh + remote-exec: + - inline: + - sudo bash /tmp/create-docker.engine.sh + - sudo bash /tmp/configure-docker.engine.sh + - sudo bash /tmp/start-docker.engine.sh + - inline: + - sudo bash /tmp/stop-docker.engine.sh + - sudo bash /tmp/delete-docker.engine.sh + when: destroy + mysql.dbms~mysql.dbms#dbms.image::ansible@docker.engine->local.machine: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 application_port: - type: integer + type: string default: 3306 management_address: type: string default: - eval: .::application_address + eval: .::.requirements::[.name=host]::.target::management_address management_port: type: integer + default: 3306 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.dbms_name }}' + image: mysql:{{ ".artifacts::dbms_image::file" | eval }} + network_mode: host + env: + MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password | string }}' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: delete container + community.docker.docker_container: + name: '{{ SELF.dbms_name }}' + state: absent + mysql.dbms~mysql.dbms#dbms.image::compose@docker.engine->local.machine: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + application_port: + type: integer + default: 3306 + management_address: + type: string default: - eval: .::application_port + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: 3306 + capabilities: + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address interfaces: Standard: operations: @@ -7818,61 +7758,26 @@ node_types: inputs: playbook: q: - - name: touch manifest - register: manifest + - name: touch compose + register: compose ansible.builtin.tempfile: - suffix: '{{ SELF.dbms_name }}.dbms.manifest.yaml' - - name: create manifest + suffix: '{{ SELF.dbms_name }}.compose.yaml' + - name: create compose ansible.builtin.copy: - dest: '{{ manifest.path }}' - content: | - {{ deployment | to_yaml }} - --- - {{ service | to_yaml }} + dest: '{{ compose.path }}' + content: '{{ manifest | 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: 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 }} rollout status deployment/{{ SELF.dbms_name }} --timeout 60s + 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: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: executable: /usr/bin/bash - name: let it cook @@ -7885,97 +7790,5333 @@ node_types: inputs: playbook: q: - - name: touch manifest - register: manifest + - 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 + mysql.dbms~mysql.dbms#dbms.image::terraform@docker.engine->local.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: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + application_port: + type: integer + default: 3306 + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: 3306 + capabilities: + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - name: '{{ SELF.dbms_name }}' + image: ${docker_image.image.image_id} + network_mode: host + env: + - MYSQL_ROOT_PASSWORD={{ SELF.dbms_password }} + docker_image: + image: + - name: mysql:{{ ".artifacts::dbms_image::file" | eval }} + mysql.dbms~mysql.dbms#dbms.image::ansible@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: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + application_port: + type: string + default: 3306 + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: 3306 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.dbms_name }}' + image: mysql:{{ ".artifacts::dbms_image::file" | eval }} + network_mode: host + env: + MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password | string }}' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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 }}' + 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_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + application_port: + type: integer + default: 3306 + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: 3306 + capabilities: + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + interfaces: + Standard: + operations: + create: + 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: 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: let it cook + ansible.builtin.pause: + seconds: 10 + 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.dbms~mysql.dbms#dbms.image::terraform@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: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + application_port: + type: integer + default: 3306 + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: 3306 + capabilities: + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + required_version: '>= 0.14.0' + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - name: '{{ SELF.dbms_name }}' + image: ${docker_image.image.image_id} + network_mode: host + env: + - MYSQL_ROOT_PASSWORD={{ SELF.dbms_password }} + docker_image: + image: + - name: mysql:{{ ".artifacts::dbms_image::file" | eval }} + mysql.dbms~mysql.dbms#dbms.image::ansible@gcp.cloudsql: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + dbms_ssl_mode: + type: string + default: Preferred + attributes: + application_port: + type: string + default: 3306 + management_address: + type: string + default: + eval: .::application_address + management_port: + type: integer + default: + eval: .::application_port + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: + - name: create a instance + register: instance_info + google.cloud.gcp_sql_instance: + name: '{{ SELF.dbms_name }}' + database_version: MYSQL_{{ ".artifacts::dbms_image::file" | eval | replace(".", "_") }} + settings: + tier: db-f1-micro + availability_type: REGIONAL + backup_configuration: + binary_log_enabled: true + enabled: true + ip_configuration: + authorized_networks: + - value: 0.0.0.0/0 + region: '{{ SELF.gcp_region }}' + project: '{{ SELF.gcp_project }}' + - name: set root password + google.cloud.gcp_sql_user: + name: root + host: '%' + password: '{{ SELF.dbms_password }}' + instance: '{{ instance_info }}' + project: '{{ SELF.gcp_project }}' + - name: aet attributes + set_fact: + application_address: '{{ instance_info.ipAddresses[0].ipAddress | trim }}' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address }}' + outputs: + application_address: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: Activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: Delete Instance + ansible.builtin.shell: gcloud sql instances delete {{ SELF.dbms_name }} --quiet + args: + executable: /bin/bash + mysql.dbms~mysql.dbms#dbms.image::terraform@gcp.cloudsql: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + dbms_ssl_mode: + type: string + default: Preferred + attributes: + application_port: + type: string + default: 3306 + management_address: + type: string + default: + eval: .::application_address + management_port: + type: integer + default: + eval: .::application_port + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 4.67.0 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: ${google_sql_database_instance.dbms.public_ip_address} + resource: + google_sql_database_instance: + dbms: + - database_version: MYSQL_{{ ".artifacts::dbms_image::file" | eval | replace(".", "_") }} + deletion_protection: false + name: '{{ SELF.dbms_name }}' + root_password: '{{ SELF.dbms_password }}' + settings: + - availability_type: REGIONAL + backup_configuration: + - binary_log_enabled: true + enabled: true + ip_configuration: + - authorized_networks: + - name: public + value: 0.0.0.0/0 + ipv4_enabled: true + tier: db-f1-micro + google_sql_user: + user: + - host: '%' + instance: ${google_sql_database_instance.dbms.name} + name: root + password: ${google_sql_database_instance.dbms.root_password} + mysql.dbms~mysql.dbms#dbms.image::ansible@kubernetes.cluster: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::dbms_name + application_port: + type: integer + default: 3306 + management_address: + type: string + default: + eval: .::application_address + management_port: + type: integer + default: + eval: .::application_port + interfaces: + Standard: + operations: + create: + 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: create deployment + kubernetes.core.k8s: + wait: true + definition: + 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 + - name: create service + kubernetes.core.k8s: + definition: + apiVersion: v1 + kind: Service + metadata: + name: '{{ SELF.dbms_name }}' + namespace: default + spec: + ports: + - name: mysql + port: 3306 + targetPort: 3306 + selector: + app: '{{ SELF.dbms_name }}' + type: ClusterIP + 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::kubernetes@kubernetes.cluster: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::dbms_name + application_port: + type: integer + default: 3306 + management_address: + type: string + default: + eval: .::application_address + management_port: + type: integer + default: + eval: .::application_port + interfaces: + Standard: + operations: + create: + 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: 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 }} rollout status deployment/{{ SELF.dbms_name }} --timeout 60s + args: + executable: /usr/bin/bash + - name: let it cook + ansible.builtin.pause: + seconds: 10 + 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::terraform@kubernetes.cluster: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::dbms_name + application_port: + type: integer + default: 3306 + management_address: + type: string + default: + eval: .::application_address + management_port: + type: integer + default: + eval: .::application_port + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_deployment_v1: + application: + - metadata: + - name: '{{ SELF.dbms_name }}' + spec: + - selector: + - match_labels: + app: '{{ SELF.dbms_name }}' + template: + - metadata: + - labels: + app: '{{ SELF.dbms_name }}' + spec: + - container: + - name: '{{ SELF.dbms_name }}' + image: mysql:{{ ".artifacts::dbms_image::file" | eval }} + env: + - name: MYSQL_ROOT_PASSWORD + value: '{{ SELF.dbms_password }}' + port: + - container_port: 3306 + name: mysql + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.dbms_name }}' + spec: + - port: + - name: mysql + port: 3306 + target_port: 3306 + selector: + app: '{{ SELF.dbms_name }}' + type: ClusterIP + mysql.dbms~mysql.dbms#dbms.image::ansible@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: + type: string + default: + get_input: os_ssh_key_file + application_port: + type: string + default: 3001 + application_address: + type: string + default: 127.0.0.1 + attributes: + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: + eval: .::application_port + capabilities: + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: installing mysql + ansible.builtin.apt: + name: + - mysql-server + - mysql-client + - python3-mysqldb + - libmysqlclient-dev + state: present + update_cache: 'yes' + - name: start and enable mysql service + ansible.builtin.systemd: + name: mysql + state: started + enabled: 'yes' + - name: enable passwordless login + ansible.builtin.copy: + dest: '{{ item }}' + content: | + [client] + user=root + password={{ SELF.dbms_password }} + loop: + - /root/.my.cnf + - /home/{{ SELF.os_ssh_user }}/.my.cnf + - 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 + 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 + ansible.builtin.systemd: + name: mysql + state: restarted + - name: create all root + community.mysql.mysql_user: + name: root + password: '{{ SELF.dbms_password }}' + priv: '*.*:ALL' + host: '%' + state: present + login_host: localhost + login_password: '{{ SELF.dbms_password }}' + login_port: '{{ SELF.application_port }}' + login_user: root + - name: delete localhost root + community.mysql.mysql_user: + name: root + host: localhost + state: absent + login_host: localhost + login_password: '{{ SELF.dbms_password }}' + login_port: '{{ SELF.application_port }}' + login_user: root + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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~mysql.dbms#dbms.image::terraform@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: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_port: + type: string + default: 3001 + application_address: + type: string + default: 127.0.0.1 + attributes: + management_address: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + management_port: + type: integer + default: + eval: .::application_port + capabilities: + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: ssh + host: + eval: .parent::management_address + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + + #!/usr/bin/bash + set -e + export DEBIAN_FRONTEND="noninteractive" + + DBMS_PASSWORD=$1 + DBMS_PORT=$2 + + # Set password + debconf-set-selections <<< "mysql-server mysql-server/root_password password ${DBMS_PASSWORD}" + debconf-set-selections <<< "mysql-server mysql-server/root_password_again password ${DBMS_PASSWORD}" + + # Install mysql + apt-get update -y + apt-get -y install mysql-server + + # Passwordless auth + cat < /root/.my.cnf + [client] + user=root + password=${DBMS_PASSWORD} + EOF + + # Listen on all interfaces + sed -i "s/127\.0\.0\.1/0\.0\.0\.0/g" /etc/mysql/mysql.conf.d/mysqld.cnf + + # Listen on custom port + sed -i "s/# port.*/port = ${DBMS_PORT}/g" /etc/mysql/mysql.conf.d/mysqld.cnf + + # Configure any host for root + mysql -u root -e 'USE mysql; UPDATE user SET host = "%" WHERE user = "root"; FLUSH PRIVILEGES;' + mysql -u root -e 'USE mysql; DELETE FROM user WHERE user = "root" and host = "localhost"; FLUSH PRIVILEGES;' + + # Enable service + systemctl enable mysql + + # Restart service + systemctl restart mysql + destination: /tmp/install-mysql-dbms.sh + remote-exec: + - inline: + - sudo bash /tmp/install-mysql-dbms.sh {{ SELF.dbms_password }} {{ SELF.application_port }} + mysql.dbms~software.application#apt.package::ansible@*->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: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + mysql.dbms~software.application#apt.archive::terraform@*->remote.machine: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + DBMS_NAME="{{ SELF.dbms_name }}" + APPLICATION_NAME="{{ SELF.application_name }}" + DBMS_PASSWORD="{{ SELF.dbms_password }}" + DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-mysql.dbms {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-mysql.dbms.sh + remote-exec: + - inline: + - sudo bash /tmp/create-mysql.dbms.sh + - sudo bash /tmp/configure-mysql.dbms.sh + - sudo bash /tmp/start-mysql.dbms.sh + - inline: + - sudo bash /tmp/stop-mysql.dbms.sh + - sudo bash /tmp/delete-mysql.dbms.sh + when: destroy + mysql.dbms~software.application#tar.archive::ansible@*->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: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: |- + DBMS_NAME="{{ SELF.dbms_name }}" + APPLICATION_NAME="{{ SELF.application_name }}" + DBMS_PASSWORD="{{ SELF.dbms_password }}" + DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + mysql.dbms~software.application#tar.archive::terraform@*->remote.machine: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-mysql.dbms + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + DBMS_NAME="{{ SELF.dbms_name }}" + APPLICATION_NAME="{{ SELF.application_name }}" + DBMS_PASSWORD="{{ SELF.dbms_password }}" + DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-mysql.dbms {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-mysql.dbms -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-mysql.dbms.sh + remote-exec: + - inline: + - sudo bash /tmp/create-mysql.dbms.sh + - sudo bash /tmp/configure-mysql.dbms.sh + - sudo bash /tmp/start-mysql.dbms.sh + - inline: + - sudo bash /tmp/stop-mysql.dbms.sh + - sudo bash /tmp/delete-mysql.dbms.sh + when: destroy + mysql.dbms~software.application#zip.archive::ansible@*->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: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: |- + DBMS_NAME="{{ SELF.dbms_name }}" + APPLICATION_NAME="{{ SELF.application_name }}" + DBMS_PASSWORD="{{ SELF.dbms_password }}" + DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + mysql.dbms~software.application#zip.archive::terraform@*->remote.machine: + derived_from: mysql.dbms + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-mysql.dbms + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + DBMS_NAME="{{ SELF.dbms_name }}" + APPLICATION_NAME="{{ SELF.application_name }}" + DBMS_PASSWORD="{{ SELF.dbms_password }}" + DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-mysql.dbms {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-mysql.dbms -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-mysql.dbms.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-mysql.dbms.sh + remote-exec: + - inline: + - sudo bash /tmp/create-mysql.dbms.sh + - sudo bash /tmp/configure-mysql.dbms.sh + - sudo bash /tmp/start-mysql.dbms.sh + - inline: + - sudo bash /tmp/stop-mysql.dbms.sh + - sudo bash /tmp/delete-mysql.dbms.sh + when: destroy + mysql.database~mysql.database::ansible@mysql.dbms->docker.engine->local.machine: + derived_from: mysql.database + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: get dbms container info + community.docker.docker_container_info: + name: '{{ HOST.dbms_name }}' + register: dbms_container_info + - 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 + - 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 + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - 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 + mysql.database~mysql.database::compose@mysql.dbms->docker.engine->local.machine: + derived_from: mysql.database + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + interfaces: + Standard: + operations: + create: + 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' + - 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 + 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 + - 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 + mysql.database~mysql.database::terraform@mysql.dbms->docker.engine->local.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: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - mysql: + source: petoju/mysql + version: 3.0.48 + provider: + mysql: + - endpoint: 127.0.0.1:{{ HOST.management_port }} + password: '{{ HOST.dbms_password }}' + username: root + resource: + mysql_database: + database: + - name: '{{ SELF.database_name }}' + mysql_user: + user: + - host: '%' + plaintext_password: '{{ SELF.database_password }}' + user: '{{ SELF.database_user }}' + mysql_grant: + user: + - database: '{{ SELF.database_name }}' + host: '%' + table: '*' + privileges: + - ALL + user: ${mysql_user.user.user} + mysql.database~mysql.database::ansible@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: + type: string + default: + get_input: os_ssh_key_file + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install pip + ansible.builtin.apt: + name: python3-pip + state: present + - name: install pymysql + ansible.builtin.pip: + name: pymysql + state: present + - name: get dbms container info + community.docker.docker_container_info: + name: '{{ HOST.dbms_name }}' + register: dbms_container_info + - name: forward port + when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" + community.docker.docker_container: + name: '{{ HOST.dbms_name }}-port-forward' + image: nicolaka/netshoot:v0.13 + command: socat TCP6-LISTEN:3306,fork TCP:{{ HOST.dbms_name }}:3306 + ports: + - '{{ HOST.application_port }}:3306' + - name: create forwarding network + community.docker.docker_network: + name: '{{ HOST.dbms_name }}-port-forward' + connected: + - '{{ HOST.dbms_name }}-port-forward' + - '{{ HOST.dbms_name }}' + when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" + - 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 + - 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 + - name: unforward port + when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" + community.docker.docker_container: + name: '{{ HOST.dbms_name }}-port-forward' + state: absent + - name: remove forwarding network + community.docker.docker_network: + name: '{{ HOST.dbms_name }}-port-forward' + state: absent + when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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::compose@mysql.dbms->docker.engine->remote.machine: + derived_from: mysql.database + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + interfaces: + Standard: + operations: + create: + 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' + - 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 + 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 }}' + 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 }}' + mysql.database~mysql.database::terraform@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: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - mysql: + source: petoju/mysql + version: 3.0.48 + ssh: + source: AndrewChubatiuk/ssh + version: 0.2.3 + data: + ssh_tunnel: + mysql: + - remote: + host: '{{ HOST.application_address }}' + port: '{{ HOST.application_port }}' + provider: + mysql: + - endpoint: ${data.ssh_tunnel.mysql.local.address} + password: '{{ HOST.dbms_password }}' + username: root + ssh: + - auth: + private_key: + content: ${file(pathexpand("{{ SELF.os_ssh_key_file }}"))} + server: + host: '{{ HOST.management_address }}' + port: 22 + user: '{{ SELF.os_ssh_user }}' + resource: + mysql_database: + database: + - name: '{{ SELF.database_name }}' + mysql_user: + user: + - host: '%' + plaintext_password: '{{ SELF.database_password }}' + user: '{{ SELF.database_user }}' + mysql_grant: + user: + - database: '{{ SELF.database_name }}' + host: '%' + table: '*' + privileges: + - ALL + user: ${mysql_user.user.user} + mysql.database~mysql.database::ansible@mysql.dbms->gcp.cloudsql: + derived_from: mysql.database + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + environment: + GCP_SERVICE_ACCOUNT_FILE: + eval: .::gcp_service_account_file + GCP_AUTH_KIND: serviceaccount + inputs: + playbook: + q: + - name: create a database + google.cloud.gcp_sql_database: + name: '{{ SELF.database_name }}' + charset: utf8 + instance: '{{ HOST.dbms_name }}' + project: '{{ SELF.gcp_project }}' + - name: install GCP CloudSQL Proxy + ansible.builtin.get_url: + url: https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.13.0/cloud-sql-proxy.linux.amd64 + dest: /tmp/gcp-cloudsql-proxy + mode: '0755' + - name: forward port + ansible.builtin.shell: '/tmp/gcp-cloudsql-proxy {{ SELF.gcp_project }}:{{ SELF.gcp_region }}:{{ HOST.dbms_name }} --credentials-file {{ SELF.gcp_service_account_file }} --port 23306 ' + args: + executable: /usr/bin/bash + async: 30 + poll: 0 + - name: wait for port + ansible.builtin.wait_for: + host: 127.0.0.1 + port: 23306 + delay: 5 + timeout: 30 + - name: create user (with privileges) + community.mysql.mysql_user: + name: '{{ SELF.database_user }}' + password: '{{ SELF.database_password }}' + host: '%' + priv: '*.*:ALL' + login_host: 127.0.0.1 + login_password: '{{ HOST.dbms_password }}' + login_port: 23306 + login_user: root + - name: unforward port + ansible.builtin.shell: pkill -f "/tmp/gcp-cloudsql-proxy {{ SELF.gcp_project }}:{{ SELF.gcp_region }}:{{ HOST.dbms_name }}" + args: + executable: /usr/bin/bash + mysql.database~mysql.database::terraform@mysql.dbms->gcp.cloudsql: + derived_from: mysql.database + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + delete: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + mysql: + source: petoju/mysql + version: 3.0.48 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + mysql: + - endpoint: cloudsql://{{ SELF.gcp_project }}:{{ SELF.gcp_region }}:{{ HOST.dbms_name }} + password: '{{ HOST.dbms_password }}' + username: root + resource: + google_sql_database: + database: + - name: '{{ SELF.database_name }}' + instance: '{{ HOST.dbms_name }}' + google_sql_user: + user: + - host: '%' + instance: '{{ HOST.dbms_name }}' + name: '{{ SELF.database_name }}' + password: '{{ SELF.database_password }}' + mysql_grant: + user: + - database: '{{ SELF.database_name }}' + host: '%' + table: '*' + privileges: + - ALL + user: ${google_sql_user.user.name} + mysql.database~mysql.database::ansible@mysql.dbms->kubernetes.cluster: + derived_from: mysql.database + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: deploy database + block: + - name: forward port + 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 + poll: 0 + - name: wait for port + ansible.builtin.wait_for: + host: 127.0.0.1 + port: 23306 + delay: 5 + timeout: 30 + - name: create database + community.mysql.mysql_db: + name: '{{ SELF.database_name }}' + login_host: 127.0.0.1 + login_password: '{{ HOST.dbms_password }}' + login_port: '23306' + login_user: root + - name: create user (with privileges) + community.mysql.mysql_user: + name: '{{ SELF.database_user }}' + password: '{{ SELF.database_password }}' + host: '%' + priv: '*.*:ALL' + login_host: 127.0.0.1 + login_password: '{{ HOST.dbms_password }}' + login_port: '23306' + login_user: root + always: + - name: unforward port + ansible.builtin.shell: pkill -f "port-forward service/{{ HOST.dbms_name }}" + args: + executable: /usr/bin/bash + mysql.database~mysql.database::kubernetes@mysql.dbms->kubernetes.cluster: + derived_from: mysql.database + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + interfaces: + Standard: + operations: + create: + 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 + - '--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 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 + - '--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 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 + mysql.database~mysql.database::terraform@mysql.dbms->kubernetes.cluster: + derived_from: mysql.database + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - mysql: + source: petoju/mysql + version: 3.0.48 + provider: + mysql: + - endpoint: ${terraform_data.forward_port.input} + password: '{{ HOST.dbms_password }}' + username: root + resource: + terraform_data: + forward_port: + - input: 127.0.0.1:23306 + provisioner: + local-exec: + command: |- + (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 + - '-c' + unforward_port: + - depends_on: + - mysql_grant.user + provisioner: + local-exec: + command: pkill -f "port-forward service/{{ HOST.dbms_name }}" + interpreter: + - /bin/bash + - '-c' + mysql_database: + database: + - name: '{{ SELF.database_name }}' + mysql_user: + user: + - host: '%' + plaintext_password: '{{ SELF.database_password }}' + user: '{{ SELF.database_user }}' + mysql_grant: + user: + - database: '{{ SELF.database_name }}' + host: '%' + table: '*' + privileges: + - ALL + user: ${mysql_user.user.user} + mysql.database~mysql.database::ansible@mysql.dbms->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: + type: string + default: + get_input: os_ssh_key_file + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install pip + ansible.builtin.apt: + name: python3-pip + state: present + - name: install pymysql + ansible.builtin.pip: + name: pymysql + state: present + - 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 + - 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 + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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->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: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - mysql: + source: petoju/mysql + version: 3.0.48 + ssh: + source: AndrewChubatiuk/ssh + version: 0.2.3 + data: + ssh_tunnel: + mysql: + - remote: + host: '{{ HOST.application_address }}' + port: '{{ HOST.application_port }}' + provider: + mysql: + - endpoint: ${data.ssh_tunnel.mysql.local.address} + password: '{{ HOST.dbms_password }}' + username: root + ssh: + - auth: + private_key: + content: ${file(pathexpand("{{ SELF.os_ssh_key_file }}"))} + server: + host: '{{ HOST.management_address }}' + port: 22 + user: '{{ SELF.os_ssh_user }}' + resource: + mysql_database: + database: + - name: '{{ SELF.database_name }}' + mysql_user: + user: + - host: '%' + plaintext_password: '{{ SELF.database_password }}' + user: '{{ SELF.database_user }}' + mysql_grant: + user: + - database: '{{ SELF.database_name }}' + host: '%' + table: '*' + privileges: + - ALL + user: ${mysql_user.user.user} + minio.server~service.application#docker.image::ansible@docker.engine->local.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + minio.server~service.application#docker.image::compose@docker.engine->local.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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: unapply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + minio.server~service.application#docker.image::terraform@docker.engine->local.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + required_version: '>= 0.14.0' + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + minio.server~service.application#docker.image::ansible@docker.engine->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: {} + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + 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 }}' + minio.server~service.application#docker.image::compose@docker.engine->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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 }} up -d + args: + executable: /usr/bin/bash + 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: unapply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down + args: + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + minio.server~service.application#docker.image::terraform@docker.engine->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - env: [] + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + minio.server~service.application#docker.image::ansible@gcp.cloudrun: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: touch service + register: service + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.service.yaml' + - name: create service + ansible.builtin.copy: + dest: '{{ service.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + apiVersion: serving.knative.dev/v1 + kind: Service + metadata: + name: '{{ SELF.application_name }}' + labels: + cloud.googleapis.com/location: '{{ SELF.gcp_region }}' + annotations: + run.googleapis.com/ingress: all + spec: + template: + spec: + containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + containerPort: '{{ SELF.application_port }}' + env: [] + - name: apply service + ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet + args: + executable: /bin/bash + - name: touch policy + register: policy + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.policy.yaml' + - name: fill policy + ansible.builtin.copy: + dest: '{{ policy.path }}' + content: '{{ manifest | to_yaml }}' + vars: + manifest: + bindings: + - members: + - allUsers + role: roles/run.invoker + - name: apply policy + ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + - name: describe service + register: service_description + ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + minio.server~service.application#docker.image::terraform@gcp.cloudrun: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' + resource: + google_cloud_run_v2_service: + application: + - ingress: INGRESS_TRAFFIC_ALL + location: '{{ SELF.gcp_region }}' + name: '{{ SELF.application_name }}' + template: + - containers: + - image: '{{ ".artifacts::docker_image::file" | eval }}' + ports: + - name: http1 + container_port: '{{ SELF.application_port }}' + env: [] + google_cloud_run_service_iam_binding: + application: + - location: '{{ SELF.gcp_region }}' + members: + - allUsers + role: roles/run.invoker + service: '{{ SELF.application_name }}' + minio.server~service.application#docker.image::ansible@kubernetes.cluster: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: create deployment + kubernetes.core.k8s: + wait: true + definition: + 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 }}' + - name: create service + kubernetes.core.k8s: + definition: + 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 + 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 }}' + minio.server~service.application#docker.image::kubernetes@kubernetes.cluster: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + create: + 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: 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 }} 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 + minio.server~service.application#docker.image::terraform@kubernetes.cluster: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + k8s_host: + type: string + default: + get_input: k8s_host + k8s_ca_cert_file: + type: string + default: + get_input: k8s_ca_cert_file + k8s_client_cert_file: + type: string + default: + get_input: k8s_client_cert_file + k8s_client_key_file: + type: string + default: + get_input: k8s_client_key_file + attributes: + application_address: + type: string + default: + eval: .::application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - kubernetes: + source: hashicorp/kubernetes + version: 2.31.0 + required_version: '>= 0.14.0' + provider: + kubernetes: + - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} + client_key: ${file("{{ SELF.k8s_client_key_file }}")} + cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} + host: '{{ SELF.k8s_host }}' + resource: + kubernetes_deployment_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - selector: + - match_labels: + app: '{{ SELF.application_name }}' + template: + - metadata: + - labels: + app: '{{ SELF.application_name }}' + spec: + - container: + - env: [] + image: '{{ ".artifacts::docker_image::file" | eval }}' + name: '{{ SELF.application_name }}' + port: + - container_port: '{{ SELF.application_port }}' + kubernetes_service_v1: + application: + - metadata: + - name: '{{ SELF.application_name }}' + spec: + - port: + - name: '{{ SELF.application_protocol }}' + port: '{{ SELF.application_port }}' + target_port: '{{ SELF.application_port }}' + selector: + app: '{{ SELF.application_name }}' + type: ClusterIP + minio.server~service.application#tar.archive::ansible@*->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + minio.server~service.application#tar.archive::terraform@*->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-minio.server + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-minio.server {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-minio.server -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-minio.server.sh + remote-exec: + - inline: + - sudo bash /tmp/create-minio.server.sh + - sudo bash /tmp/configure-minio.server.sh + - sudo bash /tmp/start-minio.server.sh + - inline: + - sudo bash /tmp/stop-minio.server.sh + - sudo bash /tmp/delete-minio.server.sh + when: destroy + minio.server~service.application#zip.archive::ansible@*->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: create service + ansible.builtin.copy: + dest: /etc/systemd/system/{{ SELF.application_name }}.service + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + - name: enable service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: started + enabled: 'yes' + daemon_reload: 'yes' + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: stop service + ansible.builtin.systemd: + name: '{{ SELF.application_name }}' + state: stopped + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + delete: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete systemd service + ansible.builtin.file: + path: /etc/systemd/system/{{ SELF.application_name }}.service + state: absent + - name: reload daemon + ansible.builtin.systemd: + daemon_reload: true + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + minio.server~service.application#zip.archive::terraform@*->remote.machine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + resource: + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-minio.server + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + destination: /etc/systemd/system/{{ SELF.application_name }}.service + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-minio.server {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-minio.server -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Reload systemd daemon + systemctl daemon-reload + + # Enable service + systemctl enable {{ SELF.application_name }} + destination: /tmp/create-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Start service + systemctl start {{ SELF.application_name }} + destination: /tmp/start-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + + # Stop service + systemctl stop {{ SELF.application_name }} + destination: /tmp/stop-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Delete systemd service + rm -f /etc/systemd/system/{{ SELF.application_name }}.service + + # Reload system daemon + systemctl daemon-reload + destination: /tmp/delete-minio.server.sh + remote-exec: + - inline: + - sudo bash /tmp/create-minio.server.sh + - sudo bash /tmp/configure-minio.server.sh + - sudo bash /tmp/start-minio.server.sh + - inline: + - sudo bash /tmp/stop-minio.server.sh + - sudo bash /tmp/delete-minio.server.sh + when: destroy + minio.server~service.application#zip.archive::ansible@gcp.appengine: + derived_from: minio.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: enable GCP AppEngine + ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet + args: + executable: /bin/bash + register: app_create_command + failed_when: + - "'Created' not in app_create_command.stderr" + - "'already contains' not in app_create_command.stderr" + - name: create working directory + register: directory ansible.builtin.tempfile: - suffix: '{{ SELF.dbms_name }}.dbms.manifest.yaml' - - name: create manifest + state: directory + - name: extract deployment artifact in working directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ directory.path }}' + - name: create specification ansible.builtin.copy: - dest: '{{ manifest.path }}' - content: | - {{ deployment | to_yaml }} - --- - {{ service | to_yaml }} + dest: '{{ directory.path }}/app.yaml' + content: '{{ manifest | 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 }} + manifest: + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + instance_class: F1 + env_variables: {} + - name: create app + ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet args: - executable: /usr/bin/bash - mysql.dbms~mysql.dbms#dbms.image::terraform@kubernetes.cluster: - derived_from: mysql.dbms + executable: /bin/bash + - name: browse app + register: browse_app + ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' + args: + executable: /bin/bash + - name: set attributes + set_fact: + application_address: '{{ browse_app.stdout[8:] | trim }}' + application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' + resultTemplate: | + name: SELF + attributes: + application_address: '{{ outputs.application_address | trim }}' + application_endpoint: '{{ outputs.application_endpoint | trim }}' + outputs: + application_address: + application_endpoint: + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: activate service account + ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /bin/bash + - name: delete app + ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet + args: + executable: /bin/bash + minio.server~service.application#zip.archive::terraform@gcp.appengine: + derived_from: minio.server metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: + gcp_service_account_file: type: string default: - get_input: k8s_client_key_file - attributes: - application_address: + get_input: gcp_service_account_file + gcp_region: type: string default: - eval: .::dbms_name - application_port: - type: integer - default: 3306 - management_address: + get_input: gcp_region + gcp_project: type: string default: - eval: .::application_address - management_port: - type: integer - default: - eval: .::application_port + get_input: gcp_project interfaces: Standard: operations: @@ -7986,57 +13127,64 @@ node_types: implementation: primary: Terraform defaults: + outputs: + application_address: application_address + application_endpoint: application_endpoint inputs: main: terraform: - required_providers: - - kubernetes: - source: hashicorp/kubernetes - version: 2.31.0 - required_version: '>= 0.14.0' + - google: + source: hashicorp/google + version: 5.39.1 provider: - kubernetes: - - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} - client_key: ${file("{{ SELF.k8s_client_key_file }}")} - cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} - host: '{{ SELF.k8s_host }}' + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + output: + application_address: + - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' + application_endpoint: + - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' resource: - kubernetes_deployment_v1: - application: - - metadata: - - name: '{{ SELF.dbms_name }}' - spec: - - selector: - - match_labels: - app: '{{ SELF.dbms_name }}' - template: - - metadata: - - labels: - app: '{{ SELF.dbms_name }}' - spec: - - container: - - name: '{{ SELF.dbms_name }}' - image: mysql:{{ ".artifacts::dbms_image::file" | eval }} - env: - - name: MYSQL_ROOT_PASSWORD - value: '{{ SELF.dbms_password }}' - port: - - container_port: 3306 - name: mysql - kubernetes_service_v1: - application: - - metadata: - - name: '{{ SELF.dbms_name }}' - spec: - - port: - - name: mysql - port: 3306 - target_port: 3306 - selector: - app: '{{ SELF.dbms_name }}' - type: ClusterIP - mysql.dbms~mysql.dbms#dbms.image::ansible@remote.machine: - derived_from: mysql.dbms + google_app_engine_standard_app_version: + app: + - delete_service_on_destroy: true + deployment: + - zip: + - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} + entrypoint: + - shell: '{{ SELF._management_start }}' + env_variables: {} + runtime: '{{ SELF.application_language }}' + service: '{{ SELF.application_name }}' + service_account: ${google_service_account.custom_service_account.email} + version_id: v1 + google_project_iam_member: + gae_api: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/compute.networkUser + storage_viewer: + - member: serviceAccount:${google_service_account.custom_service_account.email} + project: ${google_service_account.custom_service_account.project} + role: roles/storage.objectViewer + google_service_account: + custom_service_account: + - account_id: '{{ SELF.application_name }}-account' + display_name: Custom Service Account + google_storage_bucket: + bucket: + - location: EU + name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' + google_storage_bucket_object: + object: + - bucket: ${google_storage_bucket.bucket.name} + name: object.zip + source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + minio.server~software.application#apt.package::ansible@*->remote.machine: + derived_from: minio.server metadata: vintner_generated: 'true' vintner_orchestrator: unfurl @@ -8049,28 +13197,14 @@ node_types: type: string default: get_input: os_ssh_key_file - application_port: - type: string - default: 3001 - application_address: - type: string - default: 127.0.0.1 - attributes: - management_address: + application_directory: type: string default: - eval: .::.requirements::[.name=host]::.target::management_address - management_port: - type: integer - default: - eval: .::application_port - capabilities: - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address + concat: + - /var/lib/ + - get_property: + - SELF + - application_name interfaces: Standard: operations: @@ -8085,66 +13219,149 @@ node_types: q: - name: wait for ssh wait_for_connection: - - name: installing mysql - ansible.builtin.apt: - name: - - mysql-server - - mysql-client - - python3-mysqldb - - libmysqlclient-dev - state: present - update_cache: 'yes' - - name: start and enable mysql service - ansible.builtin.systemd: - name: mysql - state: started - enabled: 'yes' - - name: enable passwordless login + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation ansible.builtin.copy: - dest: '{{ item }}' - content: | - [client] - user=root - password={{ SELF.dbms_password }} - loop: - - /root/.my.cnf - - /home/{{ SELF.os_ssh_user }}/.my.cnf - - 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 - 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 - ansible.builtin.systemd: - name: mysql - state: restarted - - name: create all root - community.mysql.mysql_user: - name: root - password: '{{ SELF.dbms_password }}' - priv: '*.*:ALL' - host: '%' - state: present - login_host: localhost - login_password: '{{ SELF.dbms_password }}' - login_port: '{{ SELF.application_port }}' - login_user: root - - name: delete localhost root - community.mysql.mysql_user: - name: root - host: localhost - state: absent - login_host: localhost - login_password: '{{ SELF.dbms_password }}' - login_port: '{{ SELF.application_port }}' - login_user: root + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" playbookArgs: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' @@ -8160,30 +13377,38 @@ node_types: 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 + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory ansible.builtin.file: - name: '{{ item }}' + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' 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~mysql.dbms#dbms.image::terraform@remote.machine: - derived_from: mysql.dbms + minio.server~software.application#apt.archive::terraform@*->remote.machine: + derived_from: minio.server metadata: vintner_generated: 'true' - vintner_orchestrator: unfurl properties: os_ssh_user: type: string @@ -8197,28 +13422,14 @@ node_types: type: string default: eval: .::.requirements::[.name=host]::.target::management_address - application_port: - type: string - default: 3001 - application_address: - type: string - default: 127.0.0.1 - attributes: - management_address: + application_directory: type: string default: - eval: .::.requirements::[.name=host]::.target::management_address - management_port: - type: integer - default: - eval: .::application_port - capabilities: - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address + concat: + - /var/lib/ + - get_property: + - SELF + - application_name interfaces: Standard: operations: @@ -8242,50 +13453,157 @@ node_types: provisioner: file: - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-minio.server {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-minio.server.sh + - content: | + #!/usr/bin/bash + set -e + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh #!/usr/bin/bash set -e - export DEBIAN_FRONTEND="noninteractive" - DBMS_PASSWORD=$1 - DBMS_PORT=$2 + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - # Set password - debconf-set-selections <<< "mysql-server mysql-server/root_password password ${DBMS_PASSWORD}" - debconf-set-selections <<< "mysql-server mysql-server/root_password_again password ${DBMS_PASSWORD}" + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-minio.server.sh + - content: | + #!/usr/bin/bash + set -e - # Install mysql - apt-get update -y - apt-get -y install mysql-server + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e - # Passwordless auth - cat < /root/.my.cnf - [client] - user=root - password=${DBMS_PASSWORD} - EOF + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh - # Listen on all interfaces - sed -i "s/127\.0\.0\.1/0\.0\.0\.0/g" /etc/mysql/mysql.conf.d/mysqld.cnf + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-minio.server.sh + - content: | + #!/usr/bin/bash + set -e - # Listen on custom port - sed -i "s/# port.*/port = ${DBMS_PORT}/g" /etc/mysql/mysql.conf.d/mysqld.cnf + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e - # Configure any host for root - mysql -u root -e 'USE mysql; UPDATE user SET host = "%" WHERE user = "root"; FLUSH PRIVILEGES;' - mysql -u root -e 'USE mysql; DELETE FROM user WHERE user = "root" and host = "localhost"; FLUSH PRIVILEGES;' + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - # Enable service - systemctl enable mysql + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-minio.server.sh + - content: | + #!/usr/bin/bash + set -e - # Restart service - systemctl restart mysql - destination: /tmp/install-mysql-dbms.sh + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-minio.server.sh remote-exec: - inline: - - sudo bash /tmp/install-mysql-dbms.sh {{ SELF.dbms_password }} {{ SELF.application_port }} - mysql.dbms~software.application#apt.package::ansible@*->remote.machine: - derived_from: mysql.dbms + - sudo bash /tmp/create-minio.server.sh + - sudo bash /tmp/configure-minio.server.sh + - sudo bash /tmp/start-minio.server.sh + - inline: + - sudo bash /tmp/stop-minio.server.sh + - sudo bash /tmp/delete-minio.server.sh + when: destroy + minio.server~software.application#tar.archive::ansible@*->remote.machine: + derived_from: minio.server metadata: vintner_generated: 'true' vintner_orchestrator: unfurl @@ -8320,40 +13638,31 @@ node_types: q: - name: wait for ssh wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - name: create application directory ansible.builtin.file: path: '{{ SELF.application_directory }}' state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: '' - name: copy management operation ansible.builtin.copy: dest: '{{ SELF.application_directory }}/.vintner/create.sh' @@ -8416,6 +13725,10 @@ node_types: q: - name: wait for ssh wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - name: copy management operation ansible.builtin.copy: dest: '{{ SELF.application_directory }}/.vintner/start.sh' @@ -8447,6 +13760,10 @@ node_types: q: - name: wait for ssh wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - name: copy management operation ansible.builtin.copy: dest: '{{ SELF.application_directory }}/.vintner/stop.sh' @@ -8498,16 +13815,12 @@ node_types: ansible.builtin.file: path: '{{ SELF.application_directory }}' state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent playbookArgs: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - mysql.dbms~software.application#apt.archive::terraform@*->remote.machine: - derived_from: mysql.dbms + minio.server~software.application#tar.archive::terraform@*->remote.machine: + derived_from: minio.server metadata: vintner_generated: 'true' properties: @@ -8553,54 +13866,28 @@ node_types: user: '{{ SELF.os_ssh_user }}' provisioner: file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-minio.server + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - content: | #!/usr/bin/bash set -e - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - # Create application directory mkdir -p {{ SELF.application_directory }} # Create application environment cat < {{ SELF.application_directory }}/.env - DBMS_NAME="{{ SELF.dbms_name }}" - APPLICATION_NAME="{{ SELF.application_name }}" - DBMS_PASSWORD="{{ SELF.dbms_password }}" - DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" + EOF>> # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-mysql.dbms {{ ".artifacts::apt_archive::file" | eval }} + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-minio.server {{ ".artifacts::tar_archive::file" | eval }} fi # Extract deployment artifact - undefined + tar -xzf /tmp/artifact-minio.server -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} # Create vintner directory mkdir -p {{ SELF.application_directory }}/.vintner @@ -8618,7 +13905,7 @@ node_types: cd {{ SELF.application_directory }} . .env . .vintner/create.sh - destination: /tmp/create-mysql.dbms.sh + destination: /tmp/create-minio.server.sh - content: | #!/usr/bin/bash set -e @@ -8636,11 +13923,17 @@ node_types: cd {{ SELF.application_directory }} . .env . .vintner/configure.sh - destination: /tmp/configure-mysql.dbms.sh + destination: /tmp/configure-minio.server.sh - content: | #!/usr/bin/bash set -e + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + # Copy operation cat < {{ SELF.application_directory }}/.vintner/start.sh #!/usr/bin/bash @@ -8654,11 +13947,17 @@ node_types: cd {{ SELF.application_directory }} . .env . .vintner/start.sh - destination: /tmp/start-mysql.dbms.sh + destination: /tmp/start-minio.server.sh - content: | #!/usr/bin/bash set -e + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + # Copy operation cat < {{ SELF.application_directory }}/.vintner/stop.sh #!/usr/bin/bash @@ -8672,7 +13971,7 @@ node_types: cd {{ SELF.application_directory }} . .env . .vintner/stop.sh - destination: /tmp/stop-mysql.dbms.sh + destination: /tmp/stop-minio.server.sh - content: | #!/usr/bin/bash set -e @@ -8693,21 +13992,18 @@ node_types: # Delete application directory rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-mysql.dbms.sh + destination: /tmp/delete-minio.server.sh remote-exec: - inline: - - sudo bash /tmp/create-mysql.dbms.sh - - sudo bash /tmp/configure-mysql.dbms.sh - - sudo bash /tmp/start-mysql.dbms.sh + - sudo bash /tmp/create-minio.server.sh + - sudo bash /tmp/configure-minio.server.sh + - sudo bash /tmp/start-minio.server.sh - inline: - - sudo bash /tmp/stop-mysql.dbms.sh - - sudo bash /tmp/delete-mysql.dbms.sh + - sudo bash /tmp/stop-minio.server.sh + - sudo bash /tmp/delete-minio.server.sh when: destroy - mysql.dbms~software.application#tar.archive::ansible@*->remote.machine: - derived_from: mysql.dbms + minio.server~software.application#zip.archive::ansible@*->remote.machine: + derived_from: minio.server metadata: vintner_generated: 'true' vintner_orchestrator: unfurl @@ -8742,23 +14038,26 @@ node_types: q: - name: wait for ssh wait_for_connection: + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' - name: create application directory ansible.builtin.file: path: '{{ SELF.application_directory }}' state: directory - name: extract deployment artifact in application directory ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") - name: create vintner directory ansible.builtin.file: path: '{{ SELF.application_directory }}/.vintner' @@ -8766,11 +14065,7 @@ node_types: - name: create .env file ansible.builtin.copy: dest: '{{ SELF.application_directory }}/.env' - content: |- - DBMS_NAME="{{ SELF.dbms_name }}" - APPLICATION_NAME="{{ SELF.application_name }}" - DBMS_PASSWORD="{{ SELF.dbms_password }}" - DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" + content: '' - name: copy management operation ansible.builtin.copy: dest: '{{ SELF.application_directory }}/.vintner/create.sh' @@ -8927,8 +14222,8 @@ node_types: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - mysql.dbms~software.application#tar.archive::terraform@*->remote.machine: - derived_from: mysql.dbms + minio.server~software.application#zip.archive::terraform@*->remote.machine: + derived_from: minio.server metadata: vintner_generated: 'true' properties: @@ -8974,9 +14269,9 @@ node_types: user: '{{ SELF.os_ssh_user }}' provisioner: file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-mysql.dbms - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-minio.server + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - content: | #!/usr/bin/bash set -e @@ -8986,19 +14281,16 @@ node_types: # Create application environment cat < {{ SELF.application_directory }}/.env - DBMS_NAME="{{ SELF.dbms_name }}" - APPLICATION_NAME="{{ SELF.application_name }}" - DBMS_PASSWORD="{{ SELF.dbms_password }}" - DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" + EOF>> # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-mysql.dbms {{ ".artifacts::tar_archive::file" | eval }} + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-minio.server {{ ".artifacts::zip_archive::file" | eval }} fi # Extract deployment artifact - tar -xzf /tmp/artifact-mysql.dbms -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + unzip /tmp/artifact-minio.server -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} # Create vintner directory mkdir -p {{ SELF.application_directory }}/.vintner @@ -9016,7 +14308,7 @@ node_types: cd {{ SELF.application_directory }} . .env . .vintner/create.sh - destination: /tmp/create-mysql.dbms.sh + destination: /tmp/create-minio.server.sh - content: | #!/usr/bin/bash set -e @@ -9034,7 +14326,7 @@ node_types: cd {{ SELF.application_directory }} . .env . .vintner/configure.sh - destination: /tmp/configure-mysql.dbms.sh + destination: /tmp/configure-minio.server.sh - content: | #!/usr/bin/bash set -e @@ -9058,7 +14350,7 @@ node_types: cd {{ SELF.application_directory }} . .env . .vintner/start.sh - destination: /tmp/start-mysql.dbms.sh + destination: /tmp/start-minio.server.sh - content: | #!/usr/bin/bash set -e @@ -9082,7 +14374,7 @@ node_types: cd {{ SELF.application_directory }} . .env . .vintner/stop.sh - destination: /tmp/stop-mysql.dbms.sh + destination: /tmp/stop-minio.server.sh - content: | #!/usr/bin/bash set -e @@ -9103,105 +14395,251 @@ node_types: # Delete application directory rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-mysql.dbms.sh + destination: /tmp/delete-minio.server.sh remote-exec: - inline: - - sudo bash /tmp/create-mysql.dbms.sh - - sudo bash /tmp/configure-mysql.dbms.sh - - sudo bash /tmp/start-mysql.dbms.sh + - sudo bash /tmp/create-minio.server.sh + - sudo bash /tmp/configure-minio.server.sh + - sudo bash /tmp/start-minio.server.sh - inline: - - sudo bash /tmp/stop-mysql.dbms.sh - - sudo bash /tmp/delete-mysql.dbms.sh + - sudo bash /tmp/stop-minio.server.sh + - sudo bash /tmp/delete-minio.server.sh when: destroy - mysql.dbms~software.application#zip.archive::ansible@*->remote.machine: - derived_from: mysql.dbms + redis.server~redis.server#cache.image::terraform@gcp.memorystore: + derived_from: redis.server metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - os_ssh_user: + gcp_service_account_file: type: string default: - get_input: os_ssh_user - os_ssh_key_file: + get_input: gcp_service_account_file + gcp_region: type: string default: - get_input: os_ssh_key_file - application_directory: + get_input: gcp_region + gcp_project: type: string default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name + get_input: gcp_project + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + delete: + implementation: + primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file + defaults: + inputs: + main: + terraform: + - required_providers: + - google: + source: hashicorp/google + version: 5.39.1 + mysql: + source: petoju/mysql + version: 3.0.48 + provider: + google: + - credentials: '{{ SELF.gcp_service_account_file }}' + project: '{{ SELF.gcp_project }}' + region: '{{ SELF.gcp_region }}' + resource: {} + redis.server~redis.server#cache.image::ansible@docker.engine->local.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 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: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: + CACHE_NAME: '"{{ SELF.cache_name }}"' + CACHE_PORT: '"{{ SELF.cache_port }}"' + APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' + APPLICATION_NAME: '"{{ SELF.application_name }}"' + APPLICATION_PORT: '"{{ SELF.application_port }}"' + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: stop container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + state: absent + redis.server~redis.server#cache.image::compose@docker.engine->local.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: + 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: '{{ SELF.application_directory }}/.env' - content: |- - DBMS_NAME="{{ SELF.dbms_name }}" - APPLICATION_NAME="{{ SELF.application_name }}" - DBMS_PASSWORD="{{ SELF.dbms_password }}" - DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" - - name: copy management operation + 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: + CACHE_NAME: '"{{ SELF.cache_name }}"' + CACHE_PORT: '"{{ SELF.cache_port }}"' + APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' + APPLICATION_NAME: '"{{ SELF.application_name }}"' + APPLICATION_PORT: '"{{ SELF.application_port }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} up -d + args: + executable: /usr/bin/bash + 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: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh + 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: + CACHE_NAME: '"{{ SELF.cache_name }}"' + CACHE_PORT: '"{{ SELF.cache_port }}"' + APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' + APPLICATION_NAME: '"{{ SELF.application_name }}"' + APPLICATION_PORT: '"{{ SELF.application_port }}"' + - name: unapply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' + executable: /usr/bin/bash + redis.server~redis.server#cache.image::terraform@docker.engine->local.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: unix:///var/run/docker.sock + resource: + docker_container: + application: + - env: + - CACHE_NAME={{ SELF.cache_name }} + - CACHE_PORT={{ SELF.cache_port }} + - APPLICATION_PROTOCOL={{ SELF.application_protocol }} + - APPLICATION_NAME={{ SELF.application_name }} + - APPLICATION_PORT={{ SELF.application_port }} + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + redis.server~redis.server#cache.image::ansible@docker.engine->remote.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + create: implementation: primary: Ansible operation_host: HOST @@ -9212,27 +14650,22 @@ node_types: q: - name: wait for ssh wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: start container + community.docker.docker_container: + name: '{{ SELF.application_name }}' + image: '{{ ".artifacts::docker_image::file" | eval }}' + network_mode: host + env: + CACHE_NAME: '"{{ SELF.cache_name }}"' + CACHE_PORT: '"{{ SELF.cache_port }}"' + APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' + APPLICATION_NAME: '"{{ SELF.application_name }}"' + APPLICATION_PORT: '"{{ SELF.application_port }}"' playbookArgs: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - start: + delete: implementation: primary: Ansible operation_host: HOST @@ -9243,288 +14676,245 @@ node_types: q: - name: wait for ssh wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - 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 }}' - stop: + redis.server~redis.server#cache.image::compose@docker.engine->remote.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + 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: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh + 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: + CACHE_NAME: '"{{ SELF.cache_name }}"' + CACHE_PORT: '"{{ SELF.cache_port }}"' + APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' + APPLICATION_NAME: '"{{ SELF.application_name }}"' + APPLICATION_PORT: '"{{ SELF.application_port }}"' + - name: apply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} up -d args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' delete: 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: copy management operation + - name: touch compose + register: compose + ansible.builtin.tempfile: + suffix: '{{ SELF.application_name }}.compose.yaml' + - name: create compose ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh + 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: + CACHE_NAME: '"{{ SELF.cache_name }}"' + CACHE_PORT: '"{{ SELF.cache_port }}"' + APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' + APPLICATION_NAME: '"{{ SELF.application_name }}"' + APPLICATION_PORT: '"{{ SELF.application_port }}"' + - name: unapply compose + ansible.builtin.shell: docker compose -f {{ compose.path }} down args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - mysql.dbms~software.application#zip.archive::terraform@*->remote.machine: - derived_from: mysql.dbms + executable: /usr/bin/bash + environment: + DOCKER_HOST: '{{ SELF.os_ssh_host }}' + redis.server~redis.server#cache.image::terraform@docker.engine->remote.machine: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + os_ssh_user: + type: string + default: + get_input: os_ssh_user + os_ssh_key_file: + type: string + default: + get_input: os_ssh_key_file + os_ssh_host: + type: string + default: + eval: .::.requirements::[.name=host]::.target::management_address + attributes: + application_address: + type: string + default: 127.0.0.1 + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + inputs: + main: + terraform: + - required_providers: + - docker: + source: kreuzwerker/docker + version: 3.0.2 + provider: + docker: + - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 + ssh_opts: + - '-i' + - '{{ SELF.os_ssh_key_file }}' + - '-o' + - IdentitiesOnly=yes + - '-o' + - BatchMode=yes + - '-o' + - UserKnownHostsFile=/dev/null + - '-o' + - StrictHostKeyChecking=no + resource: + docker_container: + application: + - env: + - CACHE_NAME={{ SELF.cache_name }} + - CACHE_PORT={{ SELF.cache_port }} + - APPLICATION_PROTOCOL={{ SELF.application_protocol }} + - APPLICATION_NAME={{ SELF.application_name }} + - APPLICATION_PORT={{ SELF.application_port }} + image: ${docker_image.image.image_id} + name: '{{ SELF.application_name }}' + network_mode: host + docker_image: + image: + - name: '{{ ".artifacts::docker_image::file" | eval }}' + redis.server~redis.server#cache.image::ansible@kubernetes.cluster: + derived_from: redis.server + metadata: + vintner_generated: 'true' + vintner_orchestrator: unfurl + properties: + gcp_service_account_file: + type: string + default: + get_input: gcp_service_account_file + gcp_region: + type: string + default: + get_input: gcp_region + gcp_project: + type: string + default: + get_input: gcp_project + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: [] + redis.server~redis.server#cache.image::terraform@kubernetes.cluster: + derived_from: redis.server metadata: vintner_generated: 'true' + vintner_orchestrator: unfurl properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: + gcp_service_account_file: type: string default: - get_input: os_ssh_key_file - os_ssh_host: + get_input: gcp_service_account_file + gcp_region: type: string default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: + get_input: gcp_region + gcp_project: type: string default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name + get_input: gcp_project interfaces: Standard: operations: configure: implementation: primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file delete: implementation: primary: Terraform + environment: + GOOGLE_APPLICATION_CREDENTIALS: + eval: .::gcp_service_account_file defaults: inputs: main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-mysql.dbms - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - DBMS_NAME="{{ SELF.dbms_name }}" - APPLICATION_NAME="{{ SELF.application_name }}" - DBMS_PASSWORD="{{ SELF.dbms_password }}" - DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-mysql.dbms {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-mysql.dbms -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-mysql.dbms.sh - remote-exec: - - inline: - - sudo bash /tmp/create-mysql.dbms.sh - - sudo bash /tmp/configure-mysql.dbms.sh - - sudo bash /tmp/start-mysql.dbms.sh - - inline: - - sudo bash /tmp/stop-mysql.dbms.sh - - sudo bash /tmp/delete-mysql.dbms.sh - when: destroy - mysql.database~mysql.database::ansible@mysql.dbms->docker.engine->remote.machine: - derived_from: mysql.database + terraform: [] + provider: {} + resource: {} + redis.server~software.application#apt.package::ansible@*->remote.machine: + derived_from: redis.server metadata: vintner_generated: 'true' vintner_orchestrator: unfurl @@ -9537,6 +14927,14 @@ node_types: type: string default: get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name interfaces: Standard: operations: @@ -9551,67 +14949,92 @@ node_types: q: - name: wait for ssh wait_for_connection: - - name: install pip - apt: - name: python3-pip - state: present - - name: install pymysql - pip: - name: pymysql - state: present - - name: get dbms container info - community.docker.docker_container_info: - name: '{{ HOST.dbms_name }}' - register: dbms_container_info - - name: forward port - community.docker.docker_container: - name: '{{ HOST.dbms_name }}-port-forward' - image: nicolaka/netshoot:v0.13 - command: socat TCP6-LISTEN:3306,fork TCP:{{ HOST.dbms_name }}:3306 - ports: - - '{{ HOST.application_port }}:3306' - when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" - - name: create forwarding network - community.docker.docker_network: - name: '{{ HOST.dbms_name }}-port-forward' - connected: - - '{{ HOST.dbms_name }}-port-forward' - - '{{ HOST.dbms_name }}' - when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" - - 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 - - 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 - - name: unforward port - community.docker.docker_container: - name: '{{ HOST.dbms_name }}-port-forward' - image: nicolaka/netshoot:v0.13 - network_mode: host - state: absent - when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" - - name: remove forwarding network - community.docker.docker_network: - name: '{{ HOST.dbms_name }}-port-forward' - state: absent - when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" + - name: run setup script + ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + args: + executable: /bin/bash + when: '".artifacts::apt_package::script" | eval != ""' + - name: add apt key + ansible.builtin.apt_key: + url: '{{ ".artifacts::apt_package::key" | eval }}' + keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + state: present + when: '".artifacts::apt_package::key" | eval != ""' + - name: add apt repository + ansible.builtin.apt_repository: + repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} + filename: '{{ ".artifacts::apt_package::repository" | eval }}' + state: present + when: '".artifacts::apt_package::source" | eval != ""' + - name: update apt cache + ansible.builtin.apt: + update_cache: 'yes' + - name: install dependencies + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' + state: present + when: '".artifacts::apt_package::dependencies" | eval != ""' + - name: install package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: present + environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" playbookArgs: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - delete: + start: implementation: primary: Ansible operation_host: HOST @@ -9622,139 +15045,100 @@ node_types: 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 + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" playbookArgs: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' - '--user={{ SELF.os_ssh_user }}' - 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_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - interfaces: - Standard: - operations: - create: + stop: implementation: primary: Ansible - operation_host: ORCHESTRATOR + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' inputs: playbook: q: - - name: touch compose - register: compose - ansible.builtin.tempfile: - suffix: '{{ SELF.database_name }}-{{ HOST.dbms_name }}.database.compose.yaml' - - name: create compose + - name: wait for ssh + wait_for_connection: + - name: copy management operation 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 - 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 + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh args: - executable: /usr/bin/bash - environment: - DOCKER_HOST: '{{ SELF.os_ssh_host }}' + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' delete: implementation: primary: Ansible - operation_host: ORCHESTRATOR + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' inputs: playbook: q: - - name: touch compose - register: compose - ansible.builtin.tempfile: - suffix: '{{ SELF.database_name }}-{{ HOST.dbms_name }}.database.compose.yaml' - - name: create compose + - name: wait for ssh + wait_for_connection: + - name: copy management operation 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 + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh args: - executable: /usr/bin/bash - environment: - DOCKER_HOST: '{{ SELF.os_ssh_host }}' - mysql.database~mysql.database::terraform@mysql.dbms->docker.engine->remote.machine: - derived_from: mysql.database + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + - name: uninstall package + ansible.builtin.apt: + name: '{{ ".artifacts::apt_package::file" | eval }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + redis.server~software.application#apt.archive::terraform@*->remote.machine: + derived_from: redis.server metadata: vintner_generated: 'true' - vintner_orchestrator: unfurl properties: os_ssh_user: type: string @@ -9768,6 +15152,14 @@ node_types: type: string default: eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name interfaces: Standard: operations: @@ -9780,402 +15172,417 @@ node_types: defaults: inputs: main: - terraform: - - required_providers: - - mysql: - source: petoju/mysql - version: 3.0.48 - ssh: - source: AndrewChubatiuk/ssh - version: 0.2.3 - data: - ssh_tunnel: - mysql: - - remote: - host: '{{ HOST.application_address }}' - port: '{{ HOST.application_port }}' - provider: - mysql: - - endpoint: ${data.ssh_tunnel.mysql.local.address} - password: '{{ HOST.dbms_password }}' - username: root - ssh: - - auth: - private_key: - content: ${file(pathexpand("{{ SELF.os_ssh_key_file }}"))} - server: - host: '{{ HOST.management_address }}' - port: 22 - user: '{{ SELF.os_ssh_user }}' resource: - mysql_database: - database: - - name: '{{ SELF.database_name }}' - mysql_user: - user: - - host: '%' - plaintext_password: '{{ SELF.database_password }}' - user: '{{ SELF.database_user }}' - mysql_grant: - user: - - database: '{{ SELF.database_name }}' - host: '%' - table: '*' - privileges: - - ALL - user: ${mysql_user.user.user} - mysql.database~mysql.database::ansible@mysql.dbms->gcp.cloudsql: - derived_from: mysql.database - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: - - name: create a database - google.cloud.gcp_sql_database: - name: '{{ SELF.database_name }}' - charset: utf8 - instance: '{{ HOST.dbms_name }}' - project: '{{ SELF.gcp_project }}' - - name: install GCP CloudSQL Proxy - ansible.builtin.get_url: - url: https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.13.0/cloud-sql-proxy.linux.amd64 - dest: /tmp/gcp-cloudsql-proxy - mode: '0755' - - name: forward port - ansible.builtin.shell: '/tmp/gcp-cloudsql-proxy {{ SELF.gcp_project }}:{{ SELF.gcp_region }}:{{ HOST.dbms_name }} --credentials-file {{ SELF.gcp_service_account_file }} --port 23306 ' - args: - executable: /usr/bin/bash - async: 30 - poll: 0 - - name: wait for port - ansible.builtin.wait_for: - host: 127.0.0.1 - port: 23306 - delay: 5 - timeout: 30 - - name: create user (with privileges) - community.mysql.mysql_user: - name: '{{ SELF.database_user }}' - password: '{{ SELF.database_password }}' - host: '%' - priv: '*.*:ALL' - login_host: 127.0.0.1 - login_password: '{{ HOST.dbms_password }}' - login_port: 23306 - login_user: root - - name: unforward port - ansible.builtin.shell: pkill -f "/tmp/gcp-cloudsql-proxy {{ SELF.gcp_project }}:{{ SELF.gcp_region }}:{{ HOST.dbms_name }}" - args: - executable: /usr/bin/bash - mysql.database~mysql.database::terraform@mysql.dbms->gcp.cloudsql: - derived_from: mysql.database + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - content: | + #!/usr/bin/bash + set -e + + # Run setup script + if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - + fi + + # Add apt key + if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg + fi + + # Add apt repository + if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} + fi + + # Update apt cache + apt-get update -y + + # Install dependencies + if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y + fi + + # Install package + {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + CACHE_NAME="{{ SELF.cache_name }}" + CACHE_PORT="{{ SELF.cache_port }}" + APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" + APPLICATION_NAME="{{ SELF.application_name }}" + APPLICATION_PORT="{{ SELF.application_port }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-redis.server {{ ".artifacts::apt_archive::file" | eval }} + fi + + # Extract deployment artifact + undefined + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + + # Uninstall package + apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y + destination: /tmp/delete-redis.server.sh + remote-exec: + - inline: + - sudo bash /tmp/create-redis.server.sh + - sudo bash /tmp/configure-redis.server.sh + - sudo bash /tmp/start-redis.server.sh + - inline: + - sudo bash /tmp/stop-redis.server.sh + - sudo bash /tmp/delete-redis.server.sh + when: destroy + redis.server~software.application#tar.archive::ansible@*->remote.machine: + derived_from: redis.server metadata: vintner_generated: 'true' vintner_orchestrator: unfurl properties: - gcp_service_account_file: + os_ssh_user: type: string default: - get_input: gcp_service_account_file - gcp_region: + get_input: os_ssh_user + os_ssh_key_file: type: string default: - get_input: gcp_region - gcp_project: + get_input: os_ssh_key_file + application_directory: type: string default: - get_input: gcp_project + concat: + - /var/lib/ + - get_property: + - SELF + - application_name interfaces: Standard: operations: - configure: - implementation: - primary: Terraform - environment: - GOOGLE_APPLICATION_CREDENTIALS: - eval: .::gcp_service_account_file - delete: + create: implementation: - primary: Terraform + primary: Ansible + operation_host: HOST environment: - GOOGLE_APPLICATION_CREDENTIALS: - eval: .::gcp_service_account_file - defaults: - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - mysql: - source: petoju/mysql - version: 3.0.48 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - mysql: - - endpoint: cloudsql://{{ SELF.gcp_project }}:{{ SELF.gcp_region }}:{{ HOST.dbms_name }} - password: '{{ HOST.dbms_password }}' - username: root - resource: - google_sql_database: - database: - - name: '{{ SELF.database_name }}' - instance: '{{ HOST.dbms_name }}' - google_sql_user: - user: - - host: '%' - instance: '{{ HOST.dbms_name }}' - name: '{{ SELF.database_name }}' - password: '{{ SELF.database_password }}' - mysql_grant: - user: - - database: '{{ SELF.database_name }}' - host: '%' - table: '*' - privileges: - - ALL - user: ${google_sql_user.user.name} - mysql.database~mysql.database::ansible@mysql.dbms->kubernetes.cluster: - derived_from: mysql.database - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - interfaces: - Standard: - operations: - create: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::tar_archive::file" | eval).startswith("http") + - name: extract deployment artifact from URL in application directory + ansible.builtin.unarchive: + src: '{{ ".artifacts::tar_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + remote_src: 'yes' + extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' + when: (".artifacts::tar_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: |- + CACHE_NAME="{{ SELF.cache_name }}" + CACHE_PORT="{{ SELF.cache_port }}" + APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" + APPLICATION_NAME="{{ SELF.application_name }}" + APPLICATION_PORT="{{ SELF.application_port }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: implementation: primary: Ansible - operation_host: ORCHESTRATOR + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' inputs: playbook: q: - - name: deploy database - block: - - name: forward port - 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 - poll: 0 - - name: wait for port - ansible.builtin.wait_for: - host: 127.0.0.1 - port: 23306 - delay: 5 - timeout: 30 - - name: create database - community.mysql.mysql_db: - name: '{{ SELF.database_name }}' - login_host: 127.0.0.1 - login_password: '{{ HOST.dbms_password }}' - login_port: '23306' - login_user: root - - name: create user (with privileges) - community.mysql.mysql_user: - name: '{{ SELF.database_user }}' - password: '{{ SELF.database_password }}' - host: '%' - priv: '*.*:ALL' - login_host: 127.0.0.1 - login_password: '{{ HOST.dbms_password }}' - login_port: '23306' - login_user: root - always: - - name: unforward port - ansible.builtin.shell: pkill -f "port-forward service/{{ HOST.dbms_name }}" - args: - executable: /usr/bin/bash - mysql.database~mysql.database::kubernetes@mysql.dbms->kubernetes.cluster: - derived_from: mysql.database - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - interfaces: - Standard: - operations: - create: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: implementation: primary: Ansible - operation_host: ORCHESTRATOR + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' inputs: playbook: q: - - name: touch manifest - register: manifest - ansible.builtin.tempfile: - suffix: '{{ SELF.database_name }}-{{ HOST.dbms_name }}.database.manifest.yaml' - - name: create manifest + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation 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' - - 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 }} + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh 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 }} + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh args: - executable: /usr/bin/bash + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' delete: implementation: primary: Ansible - operation_host: ORCHESTRATOR + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' inputs: playbook: q: - - name: touch manifest - register: manifest - ansible.builtin.tempfile: - suffix: '{{ SELF.database_name }}-{{ HOST.dbms_name }}.database.manifest.yaml' - - name: create manifest + - name: wait for ssh + wait_for_connection: + - name: copy management operation 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' - - DROP USER IF EXISTS '{{ SELF.database_user }}'@'%'; DROP DATABASE IF EXISTS {{ SELF.database_name }}; - - 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 }} + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh args: - executable: /usr/bin/bash - mysql.database~mysql.database::terraform@mysql.dbms->kubernetes.cluster: - derived_from: mysql.database + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: absent + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + redis.server~software.application#tar.archive::terraform@*->remote.machine: + derived_from: redis.server metadata: vintner_generated: 'true' - vintner_orchestrator: unfurl properties: - k8s_host: + os_ssh_user: type: string default: - get_input: k8s_host - k8s_ca_cert_file: + get_input: os_ssh_user + os_ssh_key_file: type: string default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: + get_input: os_ssh_key_file + os_ssh_host: type: string default: - get_input: k8s_client_cert_file - k8s_client_key_file: + eval: .::.requirements::[.name=host]::.target::management_address + application_directory: type: string default: - get_input: k8s_client_key_file + concat: + - /var/lib/ + - get_property: + - SELF + - application_name interfaces: Standard: operations: @@ -10188,55 +15595,158 @@ node_types: defaults: inputs: main: - terraform: - - required_providers: - - mysql: - source: petoju/mysql - version: 3.0.48 - provider: - mysql: - - endpoint: ${terraform_data.forward_port.input} - password: '{{ HOST.dbms_password }}' - username: root resource: terraform_data: - forward_port: - - input: 127.0.0.1:23306 - provisioner: - local-exec: - command: |- - (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 - - '-c' - unforward_port: - - depends_on: - - mysql_grant.user + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' provisioner: - local-exec: - command: pkill -f "port-forward service/{{ HOST.dbms_name }}" - interpreter: - - /bin/bash - - '-c' - mysql_database: - database: - - name: '{{ SELF.database_name }}' - mysql_user: - user: - - host: '%' - plaintext_password: '{{ SELF.database_password }}' - user: '{{ SELF.database_user }}' - mysql_grant: - user: - - database: '{{ SELF.database_name }}' - host: '%' - table: '*' - privileges: - - ALL - user: ${mysql_user.user.user} - mysql.database~mysql.database::ansible@mysql.dbms->remote.machine: - derived_from: mysql.database + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' + destination: /tmp/artifact-redis.server + count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + CACHE_NAME="{{ SELF.cache_name }}" + CACHE_PORT="{{ SELF.cache_port }}" + APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" + APPLICATION_NAME="{{ SELF.application_name }}" + APPLICATION_PORT="{{ SELF.application_port }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-redis.server {{ ".artifacts::tar_archive::file" | eval }} + fi + + # Extract deployment artifact + tar -xzf /tmp/artifact-redis.server -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-redis.server.sh + remote-exec: + - inline: + - sudo bash /tmp/create-redis.server.sh + - sudo bash /tmp/configure-redis.server.sh + - sudo bash /tmp/start-redis.server.sh + - inline: + - sudo bash /tmp/stop-redis.server.sh + - sudo bash /tmp/delete-redis.server.sh + when: destroy + redis.server~software.application#zip.archive::ansible@*->remote.machine: + derived_from: redis.server metadata: vintner_generated: 'true' vintner_orchestrator: unfurl @@ -10249,6 +15759,14 @@ node_types: type: string default: get_input: os_ssh_key_file + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name interfaces: Standard: operations: @@ -10263,31 +15781,156 @@ node_types: q: - name: wait for ssh wait_for_connection: - - name: install pip - apt: - name: python3-pip - state: present - - name: install pymysql - pip: - name: pymysql - state: present - - 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 - - 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 + - name: install operational dependencies + ansible.builtin.apt: + name: unzip + update_cache: 'yes' + - name: create application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' + state: directory + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: extract deployment artifact in application directory + ansible.builtin.unarchive: + src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + dest: '{{ SELF.application_directory }}' + extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' + when: not (".artifacts::zip_archive::file" | eval).startswith("http") + - name: create vintner directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}/.vintner' + state: directory + - name: create .env file + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.env' + content: |- + CACHE_NAME="{{ SELF.cache_name }}" + CACHE_PORT="{{ SELF.cache_port }}" + APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" + APPLICATION_NAME="{{ SELF.application_name }}" + APPLICATION_PORT="{{ SELF.application_port }}" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/create.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + mode: '0755' + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/create.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + configure: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/configure.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + mode: '0755' + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/configure.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + start: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "start" missing + when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/start.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + mode: '0755' + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/start.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + playbookArgs: + - '--become' + - '--key-file={{ SELF.os_ssh_key_file }}' + - '--user={{ SELF.os_ssh_user }}' + stop: + implementation: + primary: Ansible + operation_host: HOST + environment: + ANSIBLE_HOST_KEY_CHECKING: 'False' + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + - name: assert management operation + ansible.builtin.fail: + dest: Management operation "stop" missing + when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/stop.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + mode: '0755' + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/stop.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" playbookArgs: - '--become' - '--key-file={{ SELF.os_ssh_key_file }}' @@ -10303,34 +15946,34 @@ node_types: 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 }}' + - name: copy management operation + ansible.builtin.copy: + dest: '{{ SELF.application_directory }}/.vintner/delete.sh' + content: |- + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + mode: '0755' + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: call management operation + ansible.builtin.shell: . .env && . .vintner/delete.sh + args: + chdir: '{{ SELF.application_directory }}' + executable: /bin/bash + when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" + - name: delete application directory + ansible.builtin.file: + path: '{{ SELF.application_directory }}' 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->remote.machine: - derived_from: mysql.database + redis.server~software.application#zip.archive::terraform@*->remote.machine: + derived_from: redis.server metadata: vintner_generated: 'true' - vintner_orchestrator: unfurl properties: os_ssh_user: type: string @@ -10344,6 +15987,14 @@ node_types: type: string default: eval: .::.requirements::[.name=host]::.target::management_address + application_directory: + type: string + default: + concat: + - /var/lib/ + - get_property: + - SELF + - application_name interfaces: Standard: operations: @@ -10356,47 +16007,153 @@ node_types: defaults: inputs: main: - terraform: - - required_providers: - - mysql: - source: petoju/mysql - version: 3.0.48 - ssh: - source: AndrewChubatiuk/ssh - version: 0.2.3 - data: - ssh_tunnel: - mysql: - - remote: - host: '{{ HOST.application_address }}' - port: '{{ HOST.application_port }}' - provider: - mysql: - - endpoint: ${data.ssh_tunnel.mysql.local.address} - password: '{{ HOST.dbms_password }}' - username: root - ssh: - - auth: - private_key: - content: ${file(pathexpand("{{ SELF.os_ssh_key_file }}"))} - server: - host: '{{ HOST.management_address }}' - port: 22 - user: '{{ SELF.os_ssh_user }}' resource: - mysql_database: - database: - - name: '{{ SELF.database_name }}' - mysql_user: - user: - - host: '%' - plaintext_password: '{{ SELF.database_password }}' - user: '{{ SELF.database_user }}' - mysql_grant: - user: - - database: '{{ SELF.database_name }}' - host: '%' - table: '*' - privileges: - - ALL - user: ${mysql_user.user.user} + terraform_data: + vm: + - connection: + - host: '{{ SELF.os_ssh_host }}' + private_key: ${file("{{ SELF.os_ssh_key_file }}")} + type: ssh + user: '{{ SELF.os_ssh_user }}' + provisioner: + file: + - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' + destination: /tmp/artifact-redis.server + count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' + - content: | + #!/usr/bin/bash + set -e + + # Create application directory + mkdir -p {{ SELF.application_directory }} + + # Create application environment + cat < {{ SELF.application_directory }}/.env + CACHE_NAME="{{ SELF.cache_name }}" + CACHE_PORT="{{ SELF.cache_port }}" + APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" + APPLICATION_NAME="{{ SELF.application_name }}" + APPLICATION_PORT="{{ SELF.application_port }}" + EOF>> + + # Download deployment artifact if required + if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then + wget -O /tmp/artifact-redis.server {{ ".artifacts::zip_archive::file" | eval }} + fi + + # Extract deployment artifact + unzip /tmp/artifact-redis.server -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} + + # Create vintner directory + mkdir -p {{ SELF.application_directory }}/.vintner + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/create.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/create.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/create.sh + destination: /tmp/create-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/configure.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/configure.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/configure.sh + destination: /tmp/configure-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "start" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/start.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/start.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/start.sh + destination: /tmp/start-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Assert operation + if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then + echo 'Management operation "stop" missing' + exit 1 + fi + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/stop.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/stop.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/stop.sh + destination: /tmp/stop-redis.server.sh + - content: | + #!/usr/bin/bash + set -e + + # Copy operation + cat < {{ SELF.application_directory }}/.vintner/delete.sh + #!/usr/bin/bash + set -e + + {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} + EOF>> + chmod +x {{ SELF.application_directory }}/.vintner/delete.sh + + # Execute operation + cd {{ SELF.application_directory }} + . .env + . .vintner/delete.sh + + # Delete application directory + rm -rf "{{ SELF.application_directory }}" + destination: /tmp/delete-redis.server.sh + remote-exec: + - inline: + - sudo bash /tmp/create-redis.server.sh + - sudo bash /tmp/configure-redis.server.sh + - sudo bash /tmp/start-redis.server.sh + - inline: + - sudo bash /tmp/stop-redis.server.sh + - sudo bash /tmp/delete-redis.server.sh + when: destroy diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/compose/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/compose/index.ts index 0b9df5c985..c2c4d023bc 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/compose/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/compose/index.ts @@ -21,7 +21,7 @@ const generator: ImplementationGenerator = { details: 'docker-compose manifest generated and applied', generate: (name, type) => { - const suffix = '{{ SELF.dbms_name}}' + const suffix = '{{ SELF.dbms_name }}' const manifest: DockerCompose = { name: '{{ SELF.dbms_name }}', services: { diff --git a/src/technologies/plugins/rules/utils/ansible.ts b/src/technologies/plugins/rules/utils/ansible.ts index ee01b63414..0cf4013969 100644 --- a/src/technologies/plugins/rules/utils/ansible.ts +++ b/src/technologies/plugins/rules/utils/ansible.ts @@ -222,7 +222,7 @@ export function AnsibleCreateComposeTask(options: {manifest: DockerCompose}) { export function AnsibleApplyComposeTask() { return { - name: 'unapply compose', + name: 'apply compose', 'ansible.builtin.shell': 'docker compose -f {{ compose.path }} up -d', args: { executable: '/usr/bin/bash', @@ -242,7 +242,9 @@ export function AnsibleUnapplyComposeTask() { export function AnsibleTask(options: {task: AnsibleTaskOptions; module: string; options: any}) { return { - ...options.task, + name: options.task.name, + when: options.task.when, + register: options.task.register, [options.module]: { ...options.options, }, From b1fe799160790fd5e709b77e35883fbcc98f7426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Sun, 8 Sep 2024 01:32:37 +0200 Subject: [PATCH 08/18] some local machine --- .../bucket/gcp-cloudstorage/ansible/index.ts | 1 - .../plugins/rules/generators/ingress/index.ts | 2 + .../mysql-database/mysql-dbms/index.ts | 2 + .../dbms-image/docker-engine/index.ts | 3 + .../docker-engine/machine}/index.ts | 0 .../machine}/local-machine/ansible/index.ts | 0 .../machine}/local-machine/compose/index.ts | 0 .../machine}/local-machine/index.ts | 0 .../machine}/local-machine/terraform/index.ts | 0 .../machine}/remote-machine/ansible/index.ts | 0 .../machine}/remote-machine/compose/index.ts | 0 .../machine}/remote-machine/index.ts | 0 .../remote-machine/terraform/index.ts | 0 .../gcp-cloudsql/ansible/index.ts | 0 .../gcp-cloudsql/index.ts | 0 .../gcp-cloudsql/terraform/index.ts | 0 .../{mysql-dbms-image => dbms-image}/index.ts | 4 +- .../kubernetes-cluster/ansible/index.ts | 0 .../kubernetes-cluster/index.ts | 0 .../kubernetes-cluster/kubernetes/index.ts | 0 .../kubernetes-cluster/terraform/index.ts | 0 .../mysql-dbms/dbms-image/machine/index.ts | 4 + .../machine/local-machine/ansible/index.ts | 81 +++++++ .../machine/local-machine}/index.ts | 0 .../machine/local-machine/terraform/index.ts | 87 ++++++++ .../machine/remote-machine/ansible/index.ts | 99 +++++++++ .../machine/remote-machine/index.ts | 4 + .../remote-machine/terraform/index.ts | 52 +---- .../mysql-dbms/dbms-image/machine/utils.ts | 151 +++++++++++++ .../rules/generators/mysql-dbms/index.ts | 2 +- .../remote-machine/ansible/index.ts | 208 ------------------ .../rules/generators/redis-server/index.ts | 3 + .../tar-archive/asterisk/index.ts | 2 + .../zip-archive/asterisk/index.ts | 2 + .../apt-package/asterisk/index.ts | 2 + .../tar-archive/asterisk/index.ts | 2 + .../zip-archive/asterisk/index.ts | 2 + 37 files changed, 455 insertions(+), 258 deletions(-) create mode 100644 src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/index.ts rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image/docker-engine => dbms-image/docker-engine/machine}/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image/docker-engine => dbms-image/docker-engine/machine}/local-machine/ansible/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image/docker-engine => dbms-image/docker-engine/machine}/local-machine/compose/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image/docker-engine => dbms-image/docker-engine/machine}/local-machine/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image/docker-engine => dbms-image/docker-engine/machine}/local-machine/terraform/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image/docker-engine => dbms-image/docker-engine/machine}/remote-machine/ansible/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image/docker-engine => dbms-image/docker-engine/machine}/remote-machine/compose/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image/docker-engine => dbms-image/docker-engine/machine}/remote-machine/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image/docker-engine => dbms-image/docker-engine/machine}/remote-machine/terraform/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image => dbms-image}/gcp-cloudsql/ansible/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image => dbms-image}/gcp-cloudsql/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image => dbms-image}/gcp-cloudsql/terraform/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image => dbms-image}/index.ts (53%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image => dbms-image}/kubernetes-cluster/ansible/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image => dbms-image}/kubernetes-cluster/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image => dbms-image}/kubernetes-cluster/kubernetes/index.ts (100%) rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image => dbms-image}/kubernetes-cluster/terraform/index.ts (100%) create mode 100644 src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/ansible/index.ts rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image/remote-machine => dbms-image/machine/local-machine}/index.ts (100%) create mode 100644 src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/terraform/index.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/remote-machine/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/remote-machine/index.ts rename src/technologies/plugins/rules/generators/mysql-dbms/{mysql-dbms-image => dbms-image/machine}/remote-machine/terraform/index.ts (74%) create mode 100644 src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/utils.ts delete mode 100644 src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/ansible/index.ts diff --git a/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts b/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts index 4bd0dc9b39..1a46ee957e 100644 --- a/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts @@ -8,7 +8,6 @@ const generator: ImplementationGenerator = { component: 'bucket', technology: 'ansible', hosting: ['gcp.cloudstorage'], - // TODO: which weight? most likely 1 weight: 0.5, reason: 'Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this.', diff --git a/src/technologies/plugins/rules/generators/ingress/index.ts b/src/technologies/plugins/rules/generators/ingress/index.ts index 9d63bb2693..2a0968b885 100644 --- a/src/technologies/plugins/rules/generators/ingress/index.ts +++ b/src/technologies/plugins/rules/generators/ingress/index.ts @@ -1,4 +1,6 @@ import kubernetesCluster from './kubernetes-cluster' import remoteMachine from './remote-machine' +// TODO: local machine + export default [kubernetesCluster, remoteMachine] diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/index.ts index c5f5b08145..5d42efbc7d 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/index.ts @@ -3,4 +3,6 @@ import gcpCloudSQL from './gcp-cloudsql' import kubernetesCluster from './kubernetes-cluster' import remoteMachine from './remote-machine' +// TODO: local machine + export default [dockerEngine, gcpCloudSQL, kubernetesCluster, remoteMachine] diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/index.ts new file mode 100644 index 0000000000..e5b39e1579 --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/index.ts @@ -0,0 +1,3 @@ +import machine from './machine' + +export default [machine] 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/dbms-image/docker-engine/machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/local-machine/ansible/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/ansible/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/local-machine/ansible/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/compose/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/local-machine/compose/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/compose/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/local-machine/compose/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/local-machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/local-machine/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/local-machine/terraform/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/local-machine/terraform/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/local-machine/terraform/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/remote-machine/ansible/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/ansible/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/remote-machine/ansible/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/compose/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/remote-machine/compose/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/compose/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/remote-machine/compose/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/remote-machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/remote-machine/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/remote-machine/terraform/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/docker-engine/remote-machine/terraform/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/remote-machine/terraform/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/gcp-cloudsql/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/gcp-cloudsql/ansible/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/gcp-cloudsql/ansible/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/gcp-cloudsql/ansible/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/gcp-cloudsql/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/gcp-cloudsql/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/gcp-cloudsql/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/gcp-cloudsql/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/gcp-cloudsql/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/gcp-cloudsql/terraform/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/gcp-cloudsql/terraform/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/gcp-cloudsql/terraform/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/index.ts similarity index 53% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/index.ts index c5f5b08145..70586da6c5 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/index.ts @@ -1,6 +1,6 @@ import dockerEngine from './docker-engine' import gcpCloudSQL from './gcp-cloudsql' import kubernetesCluster from './kubernetes-cluster' -import remoteMachine from './remote-machine' +import machine from './machine' -export default [dockerEngine, gcpCloudSQL, kubernetesCluster, remoteMachine] +export default [dockerEngine, gcpCloudSQL, kubernetesCluster, machine] 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/dbms-image/kubernetes-cluster/ansible/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/ansible/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/kubernetes-cluster/ansible/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/kubernetes-cluster/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/kubernetes-cluster/index.ts 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/dbms-image/kubernetes-cluster/kubernetes/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/kubernetes/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/kubernetes-cluster/kubernetes/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/kubernetes-cluster/terraform/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/kubernetes-cluster/terraform/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/kubernetes-cluster/terraform/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/index.ts new file mode 100644 index 0000000000..1fd9f3e86c --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/index.ts @@ -0,0 +1,4 @@ +import localMachine from './local-machine' +import remoteMachine from './remote-machine' + +export default [localMachine, remoteMachine] diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/ansible/index.ts new file mode 100644 index 0000000000..f3442409da --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/ansible/index.ts @@ -0,0 +1,81 @@ +import { + AnsibleMySQLDBMSInstallation, + AnsibleMySQLDBMSUninstallation, +} from '#technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/utils' +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleHostEndpointCapability, AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {LOCALHOST, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' + +const generator: ImplementationGenerator = { + component: 'mysql.dbms', + technology: 'ansible', + artifact: 'dbms.image', + hosting: ['local.machine'], + weight: 1, + reason: 'Primary use case due to the specialization of Ansible.', + details: + '"ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + application_port: { + type: 'string', + default: 3001, + }, + application_address: { + type: 'string', + default: LOCALHOST, + }, + }, + attributes: { + management_address: { + type: 'string', + default: { + eval: '.::.requirements::[.name=host]::.target::management_address', + }, + }, + management_port: { + type: 'integer', + default: {eval: '.::application_port'}, + }, + }, + capabilities: { + ...AnsibleHostEndpointCapability(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: AnsibleMySQLDBMSInstallation(), + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: AnsibleMySQLDBMSUninstallation(), + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/index.ts diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/terraform/index.ts new file mode 100644 index 0000000000..29faa09995 --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/terraform/index.ts @@ -0,0 +1,87 @@ +import { + BashMySQLDBMSInstallation, + BashMySQLDBMSInstallationScript, +} from '#technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/utils' +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleHostEndpointCapability} from '#technologies/plugins/rules/utils/ansible' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import {LOCALHOST, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' + +const generator: ImplementationGenerator = { + component: 'mysql.dbms', + technology: 'terraform', + artifact: 'dbms.image', + hosting: ['local.machine'], + weight: 0, + reason: 'Ansible is more specialized. Also using provisioners is a "last resort".', + details: + '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + application_port: { + type: 'string', + default: 3001, + }, + application_address: { + type: 'string', + default: LOCALHOST, + }, + }, + attributes: { + management_address: { + type: 'string', + default: { + eval: '.::.requirements::[.name=host]::.target::management_address', + }, + }, + management_port: { + type: 'integer', + default: {eval: '.::application_port'}, + }, + }, + capabilities: { + ...AnsibleHostEndpointCapability(), + }, + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + resource: { + local_file: { + tmp_script: { + content: BashMySQLDBMSInstallationScript, + filename: '/tmp/install-mysql-dbms.sh', + }, + }, + terraform_data: { + vm: [ + { + depends_on: 'local_file.tmp_script', + provisioner: { + 'local-exec': [ + { + inline: [BashMySQLDBMSInstallation], + }, + ], + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/remote-machine/ansible/index.ts new file mode 100644 index 0000000000..0c6eeed8ac --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/remote-machine/ansible/index.ts @@ -0,0 +1,99 @@ +import { + AnsibleMySQLDBMSInstallation, + AnsibleMySQLDBMSUninstallation, +} from '#technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/utils' +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import { + AnsibleHostEndpointCapability, + AnsibleHostOperation, + AnsibleHostOperationPlaybookArgs, + AnsibleWaitForSSHTask, +} from '#technologies/plugins/rules/utils/ansible' +import {MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials} from '#technologies/plugins/rules/utils/utils' + +const generator: ImplementationGenerator = { + component: 'mysql.dbms', + technology: 'ansible', + artifact: 'dbms.image', + hosting: ['remote.machine'], + weight: 1, + reason: 'Primary use case due to the specialization of Ansible.', + details: + '"ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...OpenstackMachineCredentials(), + application_port: { + type: 'string', + default: 3001, + }, + application_address: { + type: 'string', + default: '127.0.0.1', + }, + }, + attributes: { + management_address: { + type: 'string', + default: { + eval: '.::.requirements::[.name=host]::.target::management_address', + }, + }, + management_port: { + type: 'integer', + default: {eval: '.::application_port'}, + }, + }, + capabilities: { + ...AnsibleHostEndpointCapability(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleMySQLDBMSInstallation(), + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, + delete: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleMySQLDBMSUninstallation(), + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/remote-machine/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/remote-machine/index.ts new file mode 100644 index 0000000000..c76a810960 --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/remote-machine/index.ts @@ -0,0 +1,4 @@ +import ansible from './ansible' +import terraform from './terraform' + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/remote-machine/terraform/index.ts similarity index 74% rename from src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/terraform/index.ts rename to src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/remote-machine/terraform/index.ts index 0885dbdb3a..b65a11b29d 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/remote-machine/terraform/index.ts @@ -1,55 +1,17 @@ +import { + BashMySQLDBMSInstallation, + BashMySQLDBMSInstallationScript, +} from '#technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/utils' import {ImplementationGenerator} from '#technologies/plugins/rules/types' import {AnsibleHostEndpointCapability} from '#technologies/plugins/rules/utils/ansible' import {TerraformSSHConnection, TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { - BASH_HEADER, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, OpenstackMachineHost, } from '#technologies/plugins/rules/utils/utils' -const script = ` -${BASH_HEADER} -export DEBIAN_FRONTEND="noninteractive" - -DBMS_PASSWORD=$1 -DBMS_PORT=$2 - -# Set password -debconf-set-selections <<< "mysql-server mysql-server/root_password password $\{DBMS_PASSWORD}" -debconf-set-selections <<< "mysql-server mysql-server/root_password_again password $\{DBMS_PASSWORD}" - -# Install mysql -apt-get update -y -apt-get -y install mysql-server - -# Passwordless auth -cat < /root/.my.cnf -[client] -user=root -password=$\{DBMS_PASSWORD} -EOF - -# Listen on all interfaces -sed -i "s/127\\.0\\.0\\.1/0\\.0\\.0\\.0/g" /etc/mysql/mysql.conf.d/mysqld.cnf - -# Listen on custom port -sed -i "s/# port.*/port = $\{DBMS_PORT}/g" /etc/mysql/mysql.conf.d/mysqld.cnf - -# Configure any host for root -mysql -u root -e 'USE mysql; UPDATE user SET host = "%" WHERE user = "root"; FLUSH PRIVILEGES;' -mysql -u root -e 'USE mysql; DELETE FROM user WHERE user = "root" and host = "localhost"; FLUSH PRIVILEGES;' - -# Enable service -systemctl enable mysql - -# Restart service -systemctl restart mysql -` - -// TODO: ensure dbms_version is installed - const generator: ImplementationGenerator = { component: 'mysql.dbms', technology: 'terraform', @@ -111,15 +73,13 @@ const generator: ImplementationGenerator = { provisioner: { file: [ { - content: script, + content: BashMySQLDBMSInstallationScript, destination: '/tmp/install-mysql-dbms.sh', }, ], 'remote-exec': [ { - inline: [ - 'sudo bash /tmp/install-mysql-dbms.sh {{ SELF.dbms_password }} {{ SELF.application_port }}', - ], + inline: [BashMySQLDBMSInstallation], }, ], }, diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/utils.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/utils.ts new file mode 100644 index 0000000000..414b1619f0 --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/utils.ts @@ -0,0 +1,151 @@ +import * as files from '#files' +import {BASH_HEADER} from '#technologies/plugins/rules/utils/utils' + +// TODO: ensure dbms_version is installed + +export const BashMySQLDBMSInstallationScript = ` +${BASH_HEADER} +export DEBIAN_FRONTEND="noninteractive" + +DBMS_PASSWORD=$1 +DBMS_PORT=$2 + +# Set password +debconf-set-selections <<< "mysql-server mysql-server/root_password password $\{DBMS_PASSWORD}" +debconf-set-selections <<< "mysql-server mysql-server/root_password_again password $\{DBMS_PASSWORD}" + +# Install mysql +apt-get update -y +apt-get -y install mysql-server + +# Passwordless auth +cat < /root/.my.cnf +[client] +user=root +password=$\{DBMS_PASSWORD} +EOF + +# Listen on all interfaces +sed -i "s/127\\.0\\.0\\.1/0\\.0\\.0\\.0/g" /etc/mysql/mysql.conf.d/mysqld.cnf + +# Listen on custom port +sed -i "s/# port.*/port = $\{DBMS_PORT}/g" /etc/mysql/mysql.conf.d/mysqld.cnf + +# Configure any host for root +mysql -u root -e 'USE mysql; UPDATE user SET host = "%" WHERE user = "root"; FLUSH PRIVILEGES;' +mysql -u root -e 'USE mysql; DELETE FROM user WHERE user = "root" and host = "localhost"; FLUSH PRIVILEGES;' + +# Enable service +systemctl enable mysql + +# Restart service +systemctl restart mysql +` + +export const BashMySQLDBMSInstallation = + 'sudo bash /tmp/install-mysql-dbms.sh {{ SELF.dbms_password }} {{ SELF.application_port }}' + +export function AnsibleMySQLDBMSInstallation() { + return [ + { + name: 'installing mysql', + 'ansible.builtin.apt': { + name: ['mysql-server', 'mysql-client', 'python3-mysqldb', 'libmysqlclient-dev'], + state: 'present', + update_cache: 'yes', + }, + }, + { + name: 'start and enable mysql service', + 'ansible.builtin.systemd': { + name: 'mysql', + state: 'started', + enabled: 'yes', + }, + }, + { + name: 'enable passwordless login', + 'ansible.builtin.copy': { + dest: '{{ item }}', + content: files.toINI({ + client: { + user: 'root', + password: '{{ SELF.dbms_password }}', + }, + }), + }, + loop: ['/root/.my.cnf', '/home/{{ SELF.os_ssh_user }}/.my.cnf'], + }, + { + 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', + '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', + 'ansible.builtin.systemd': { + name: 'mysql', + state: 'restarted', + }, + }, + { + name: 'create all root', + 'community.mysql.mysql_user': { + name: 'root', + password: '{{ SELF.dbms_password }}', + priv: '*.*:ALL', + host: '%', + state: 'present', + login_host: 'localhost', + login_password: '{{ SELF.dbms_password }}', + login_port: '{{ SELF.application_port }}', + login_user: 'root', + }, + }, + { + name: 'delete localhost root', + 'community.mysql.mysql_user': { + name: 'root', + host: 'localhost', + state: 'absent', + login_host: 'localhost', + login_password: '{{ SELF.dbms_password }}', + login_port: '{{ SELF.application_port }}', + login_user: 'root', + }, + }, + ] +} + +export function AnsibleMySQLDBMSUninstallation() { + return [ + { + 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'], + }, + ] +} diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/index.ts index 262cc087e7..ffff34837e 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/index.ts @@ -1,3 +1,3 @@ -import mysqlDBMSimage from './mysql-dbms-image' +import mysqlDBMSimage from './dbms-image' export default [mysqlDBMSimage] 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 deleted file mode 100644 index 7461c2d2b5..0000000000 --- a/src/technologies/plugins/rules/generators/mysql-dbms/mysql-dbms-image/remote-machine/ansible/index.ts +++ /dev/null @@ -1,208 +0,0 @@ -import * as files from '#files' -import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - AnsibleHostEndpointCapability, - AnsibleHostOperation, - AnsibleHostOperationPlaybookArgs, - AnsibleWaitForSSHTask, -} from '#technologies/plugins/rules/utils/ansible' -import {MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials} from '#technologies/plugins/rules/utils/utils' - -// TODO: ensure dbms_version is installed - -/** - * apt-get install sudo wget lsb-release gnupg -y - * - * wget https://dev.mysql.com/get/mysql-apt-config_0.8.17-1_all.deb - * sudo dpkg -i mysql-apt-config_0.8.17-1_all.deb - */ - -const generator: ImplementationGenerator = { - component: 'mysql.dbms', - technology: 'ansible', - artifact: 'dbms.image', - hosting: ['remote.machine'], - weight: 1, - reason: 'Primary use case due to the specialization of Ansible.', - details: - '"ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks', - - generate: (name, type) => { - return { - derived_from: name, - metadata: { - ...MetadataGenerated(), - ...MetadataUnfurl(), - }, - properties: { - ...OpenstackMachineCredentials(), - application_port: { - type: 'string', - default: 3001, - }, - application_address: { - type: 'string', - default: '127.0.0.1', - }, - }, - attributes: { - management_address: { - type: 'string', - default: { - eval: '.::.requirements::[.name=host]::.target::management_address', - }, - }, - management_port: { - type: 'integer', - default: {eval: '.::application_port'}, - }, - }, - capabilities: { - ...AnsibleHostEndpointCapability(), - }, - interfaces: { - Standard: { - operations: { - create: { - implementation: { - ...AnsibleHostOperation(), - }, - inputs: { - playbook: { - q: [ - { - ...AnsibleWaitForSSHTask(), - }, - { - name: 'installing mysql', - 'ansible.builtin.apt': { - name: [ - 'mysql-server', - 'mysql-client', - 'python3-mysqldb', - 'libmysqlclient-dev', - ], - state: 'present', - update_cache: 'yes', - }, - }, - { - name: 'start and enable mysql service', - 'ansible.builtin.systemd': { - name: 'mysql', - state: 'started', - enabled: 'yes', - }, - }, - { - name: 'enable passwordless login', - 'ansible.builtin.copy': { - dest: '{{ item }}', - content: files.toINI({ - client: { - user: 'root', - password: '{{ SELF.dbms_password }}', - }, - }), - }, - loop: ['/root/.my.cnf', '/home/{{ SELF.os_ssh_user }}/.my.cnf'], - }, - { - 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', - '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', - 'ansible.builtin.systemd': { - name: 'mysql', - state: 'restarted', - }, - }, - { - name: 'create all root', - 'community.mysql.mysql_user': { - name: 'root', - password: '{{ SELF.dbms_password }}', - priv: '*.*:ALL', - host: '%', - state: 'present', - login_host: 'localhost', - login_password: '{{ SELF.dbms_password }}', - login_port: '{{ SELF.application_port }}', - login_user: 'root', - }, - }, - { - name: 'delete localhost root', - 'community.mysql.mysql_user': { - name: 'root', - host: 'localhost', - state: 'absent', - login_host: 'localhost', - login_password: '{{ SELF.dbms_password }}', - login_port: '{{ SELF.application_port }}', - login_user: 'root', - }, - }, - ], - }, - playbookArgs: [...AnsibleHostOperationPlaybookArgs()], - }, - }, - 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()], - }, - }, - }, - }, - }, - } - }, -} - -export default generator diff --git a/src/technologies/plugins/rules/generators/redis-server/index.ts b/src/technologies/plugins/rules/generators/redis-server/index.ts index 8062d15e8b..e6f1aba533 100644 --- a/src/technologies/plugins/rules/generators/redis-server/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/index.ts @@ -1,3 +1,6 @@ import cacheImage from './cache-image' +// TODO: remote-machine +// TODO: local-machine + export default [cacheImage] diff --git a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/index.ts b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/index.ts index 37846c4803..dfab123584 100644 --- a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/index.ts @@ -1,3 +1,5 @@ import remoteMachine from './remote-machine' +// TODO: local machine + export default [remoteMachine] diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/index.ts b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/index.ts index 37846c4803..dfab123584 100644 --- a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/index.ts @@ -1,3 +1,5 @@ import remoteMachine from './remote-machine' +// TODO: local machine + export default [remoteMachine] diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/index.ts index 37846c4803..dfab123584 100644 --- a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/index.ts @@ -1,3 +1,5 @@ import remoteMachine from './remote-machine' +// TODO: local machine + export default [remoteMachine] diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/index.ts index 37846c4803..dfab123584 100644 --- a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/index.ts @@ -1,3 +1,5 @@ import remoteMachine from './remote-machine' +// TODO: local machine + export default [remoteMachine] diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/index.ts index 37846c4803..dfab123584 100644 --- a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/index.ts @@ -1,3 +1,5 @@ import remoteMachine from './remote-machine' +// TODO: local machine + export default [remoteMachine] From 0bcc25b3c9f14ffc55a05d81c47d5eaf79d7468d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Sun, 8 Sep 2024 02:38:40 +0200 Subject: [PATCH 09/18] continue --- .../rules/generators/docker-engine/index.ts | 5 +- .../generators/docker-engine/machine/index.ts | 4 + .../local-machine/ansible/index.ts | 2 +- .../{ => machine}/local-machine/index.ts | 0 .../local-machine/terraform/index.ts | 2 +- .../remote-machine/ansible/index.ts | 2 +- .../{ => machine}/remote-machine/index.ts | 0 .../remote-machine/terraform/index.ts | 2 +- .../docker-engine/{ => machine}/utils.ts | 0 .../generators/service-application/index.ts | 2 + .../apt-package/asterisk/index.ts | 6 +- .../apt-package/asterisk/machine/index.ts | 4 + .../remote-machine/ansible/index.ts | 65 ++--- .../{ => machine}/remote-machine/index.ts | 0 .../remote-machine/terraform/index.ts | 142 ++--------- .../tar-archive/asterisk/index.ts | 6 +- .../tar-archive/asterisk/machine/index.ts | 4 + .../machine/local-machine/ansible/index.ts | 129 ++++++++++ .../local-machine}/index.ts | 0 .../machine/local-machine/terraform/index.ts | 116 +++++++++ .../machine/remote-machine/ansible/index.ts | 137 +++++++++++ .../asterisk/machine}/remote-machine/index.ts | 0 .../remote-machine/terraform/index.ts | 111 ++------- .../asterisk/remote-machine/ansible/index.ts | 186 -------------- .../generators/software-application/utils.ts | 230 ++++++++++++++++++ .../zip-archive/asterisk/index.ts | 6 +- .../zip-archive/asterisk/machine/index.ts | 4 + .../machine/local-machine/ansible/index.ts | 129 ++++++++++ .../asterisk/machine/local-machine/index.ts | 4 + .../machine/local-machine/terraform/index.ts | 116 +++++++++ .../remote-machine/ansible/index.ts | 108 +++----- .../asterisk/machine/remote-machine/index.ts | 4 + .../remote-machine/terraform/index.ts | 113 ++------- src/utils/utils.ts | 4 + 34 files changed, 1011 insertions(+), 632 deletions(-) create mode 100644 src/technologies/plugins/rules/generators/docker-engine/machine/index.ts rename src/technologies/plugins/rules/generators/docker-engine/{ => machine}/local-machine/ansible/index.ts (96%) rename src/technologies/plugins/rules/generators/docker-engine/{ => machine}/local-machine/index.ts (100%) rename src/technologies/plugins/rules/generators/docker-engine/{ => machine}/local-machine/terraform/index.ts (98%) rename src/technologies/plugins/rules/generators/docker-engine/{ => machine}/remote-machine/ansible/index.ts (97%) rename src/technologies/plugins/rules/generators/docker-engine/{ => machine}/remote-machine/index.ts (100%) rename src/technologies/plugins/rules/generators/docker-engine/{ => machine}/remote-machine/terraform/index.ts (97%) rename src/technologies/plugins/rules/generators/docker-engine/{ => machine}/utils.ts (100%) create mode 100644 src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/index.ts rename src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/{ => machine}/remote-machine/ansible/index.ts (80%) rename src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/{ => machine}/remote-machine/index.ts (100%) rename src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/{ => machine}/remote-machine/terraform/index.ts (59%) create mode 100644 src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts rename src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/{remote-machine => machine/local-machine}/index.ts (100%) create mode 100644 src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts create mode 100644 src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/ansible/index.ts rename src/technologies/plugins/rules/generators/software-application/{zip-archive/asterisk => tar-archive/asterisk/machine}/remote-machine/index.ts (100%) rename src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/{ => machine}/remote-machine/terraform/index.ts (70%) delete mode 100644 src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/software-application/utils.ts create mode 100644 src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts rename src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/{ => machine}/remote-machine/ansible/index.ts (51%) create mode 100644 src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/index.ts rename src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/{ => machine}/remote-machine/terraform/index.ts (69%) diff --git a/src/technologies/plugins/rules/generators/docker-engine/index.ts b/src/technologies/plugins/rules/generators/docker-engine/index.ts index 1fd9f3e86c..e5b39e1579 100644 --- a/src/technologies/plugins/rules/generators/docker-engine/index.ts +++ b/src/technologies/plugins/rules/generators/docker-engine/index.ts @@ -1,4 +1,3 @@ -import localMachine from './local-machine' -import remoteMachine from './remote-machine' +import machine from './machine' -export default [localMachine, remoteMachine] +export default [machine] diff --git a/src/technologies/plugins/rules/generators/docker-engine/machine/index.ts b/src/technologies/plugins/rules/generators/docker-engine/machine/index.ts new file mode 100644 index 0000000000..1fd9f3e86c --- /dev/null +++ b/src/technologies/plugins/rules/generators/docker-engine/machine/index.ts @@ -0,0 +1,4 @@ +import localMachine from './local-machine' +import remoteMachine from './remote-machine' + +export default [localMachine, remoteMachine] diff --git a/src/technologies/plugins/rules/generators/docker-engine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/docker-engine/machine/local-machine/ansible/index.ts similarity index 96% rename from src/technologies/plugins/rules/generators/docker-engine/local-machine/ansible/index.ts rename to src/technologies/plugins/rules/generators/docker-engine/machine/local-machine/ansible/index.ts index f871222bb0..3ae832d479 100644 --- a/src/technologies/plugins/rules/generators/docker-engine/local-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/docker-engine/machine/local-machine/ansible/index.ts @@ -1,7 +1,7 @@ import { AnsibleDockerEngineInstallationTasks, AnsibleDockerEngineUninstallationTasks, -} from '#technologies/plugins/rules/generators/docker-engine/utils' +} from '#technologies/plugins/rules/generators/docker-engine/machine/utils' import {ImplementationGenerator} from '#technologies/plugins/rules/types' import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' import {LOCALHOST, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' diff --git a/src/technologies/plugins/rules/generators/docker-engine/local-machine/index.ts b/src/technologies/plugins/rules/generators/docker-engine/machine/local-machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/docker-engine/local-machine/index.ts rename to src/technologies/plugins/rules/generators/docker-engine/machine/local-machine/index.ts diff --git a/src/technologies/plugins/rules/generators/docker-engine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/docker-engine/machine/local-machine/terraform/index.ts similarity index 98% rename from src/technologies/plugins/rules/generators/docker-engine/local-machine/terraform/index.ts rename to src/technologies/plugins/rules/generators/docker-engine/machine/local-machine/terraform/index.ts index f0a987889b..f9f0e6fbae 100644 --- a/src/technologies/plugins/rules/generators/docker-engine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/docker-engine/machine/local-machine/terraform/index.ts @@ -2,7 +2,7 @@ import { DockerEngineServiceUnit, TerraformDockerEngineInstallationTasks, TerraformDockerEngineUninstallationTasks, -} from '#technologies/plugins/rules/generators/docker-engine/utils' +} from '#technologies/plugins/rules/generators/docker-engine/machine/utils' import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { TerraformLocalProviderImport, diff --git a/src/technologies/plugins/rules/generators/docker-engine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/docker-engine/machine/remote-machine/ansible/index.ts similarity index 97% rename from src/technologies/plugins/rules/generators/docker-engine/remote-machine/ansible/index.ts rename to src/technologies/plugins/rules/generators/docker-engine/machine/remote-machine/ansible/index.ts index e7ecfd9324..9c897c42fa 100644 --- a/src/technologies/plugins/rules/generators/docker-engine/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/docker-engine/machine/remote-machine/ansible/index.ts @@ -1,7 +1,7 @@ import { AnsibleDockerEngineInstallationTasks, AnsibleDockerEngineUninstallationTasks, -} from '#technologies/plugins/rules/generators/docker-engine/utils' +} from '#technologies/plugins/rules/generators/docker-engine/machine/utils' import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleHostOperation, diff --git a/src/technologies/plugins/rules/generators/docker-engine/remote-machine/index.ts b/src/technologies/plugins/rules/generators/docker-engine/machine/remote-machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/docker-engine/remote-machine/index.ts rename to src/technologies/plugins/rules/generators/docker-engine/machine/remote-machine/index.ts diff --git a/src/technologies/plugins/rules/generators/docker-engine/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/docker-engine/machine/remote-machine/terraform/index.ts similarity index 97% rename from src/technologies/plugins/rules/generators/docker-engine/remote-machine/terraform/index.ts rename to src/technologies/plugins/rules/generators/docker-engine/machine/remote-machine/terraform/index.ts index 9843192464..db63fa0890 100644 --- a/src/technologies/plugins/rules/generators/docker-engine/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/docker-engine/machine/remote-machine/terraform/index.ts @@ -2,7 +2,7 @@ import { DockerEngineServiceUnit, TerraformDockerEngineInstallationTasks, TerraformDockerEngineUninstallationTasks, -} from '#technologies/plugins/rules/generators/docker-engine/utils' +} from '#technologies/plugins/rules/generators/docker-engine/machine/utils' import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { TerraformRequiredVersion, diff --git a/src/technologies/plugins/rules/generators/docker-engine/utils.ts b/src/technologies/plugins/rules/generators/docker-engine/machine/utils.ts similarity index 100% rename from src/technologies/plugins/rules/generators/docker-engine/utils.ts rename to src/technologies/plugins/rules/generators/docker-engine/machine/utils.ts diff --git a/src/technologies/plugins/rules/generators/service-application/index.ts b/src/technologies/plugins/rules/generators/service-application/index.ts index 448a272f30..3be390701e 100644 --- a/src/technologies/plugins/rules/generators/service-application/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/index.ts @@ -2,4 +2,6 @@ import dockerImage from './docker-image' import tarArchive from './tar-archive' import zipArchive from './zip-archive' +// TODO: apt.package + export default [dockerImage, tarArchive, zipArchive] diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/index.ts index dfab123584..e5b39e1579 100644 --- a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/index.ts @@ -1,5 +1,3 @@ -import remoteMachine from './remote-machine' +import machine from './machine' -// TODO: local machine - -export default [remoteMachine] +export default [machine] diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/index.ts new file mode 100644 index 0000000000..2e2d177edd --- /dev/null +++ b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/index.ts @@ -0,0 +1,4 @@ +import localMachine from './local-machine' +import remoteMachine from './remote-machine' + +export default [remoteMachine, localMachine] diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/ansible/index.ts similarity index 80% rename from src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/ansible/index.ts rename to src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/ansible/index.ts index 70656e7abe..ab230b193e 100644 --- a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/ansible/index.ts @@ -1,10 +1,16 @@ import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' -import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {NodeType} from '#spec/node-type' +import { + AnsibleSoftwareApplicationSourceArchiveConfigure, + AnsibleSoftwareApplicationSourceArchiveDelete, + AnsibleSoftwareApplicationSourceArchiveStart, + AnsibleSoftwareApplicationSourceArchiveStop, +} from '#technologies/plugins/rules/generators/software-application/utils' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' import { AnsibleCallManagementOperationTask, AnsibleCopyManagementOperationTask, AnsibleCreateApplicationDirectoryTask, - AnsibleDeleteApplicationDirectoryTask, AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, AnsibleWaitForSSHTask, @@ -16,17 +22,17 @@ import { OpenstackMachineCredentials, } from '#technologies/plugins/rules/utils/utils' -const generator: ImplementationGenerator = { - component: 'software.application', - technology: 'ansible', - artifact: 'apt.package', - hosting: ['*', 'remote.machine'], - weight: 1, - reason: 'Primary use case due to the specialization of Ansible.', - details: - '"ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements', +class Generator extends GeneratorAbstract { + component = 'software.application' + technology = 'ansible' + artifact = 'apt.package' + hosting = ['*', 'remote.machine'] + weight = 1 + reason = 'Primary use case due to the specialization of Ansible.' + details = + '"ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements' - generate: (name, type) => { + generate(name: string, type: NodeType) { return { derived_from: name, metadata: { @@ -125,12 +131,7 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), - }, + ...AnsibleSoftwareApplicationSourceArchiveConfigure(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -146,12 +147,7 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.START), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.START), - }, + ...AnsibleSoftwareApplicationSourceArchiveStart(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -167,12 +163,7 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), - }, + ...AnsibleSoftwareApplicationSourceArchiveStop(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -188,15 +179,7 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), - }, - { - ...AnsibleDeleteApplicationDirectoryTask(), - }, + ...AnsibleSoftwareApplicationSourceArchiveDelete(), { name: 'uninstall package', 'ansible.builtin.apt': { @@ -213,7 +196,7 @@ const generator: ImplementationGenerator = { }, }, } - }, + } } -export default generator +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/index.ts rename to src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/index.ts diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/terraform/index.ts similarity index 59% rename from src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/terraform/index.ts rename to src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/terraform/index.ts index a5549f8401..b4012c136b 100644 --- a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/terraform/index.ts @@ -1,22 +1,22 @@ -import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {NodeType} from '#spec/node-type' +import { + BashSoftwareApplicationAptPackageCreate, + BashSoftwareApplicationAptPackageDelete, + BashSoftwareApplicationConfigure, + BashSoftwareApplicationDelete, + BashSoftwareApplicationSourceArchiveCreate, + BashSoftwareApplicationStart, + BashSoftwareApplicationStop, +} from '#technologies/plugins/rules/generators/software-application/utils' import {GeneratorAbstract} from '#technologies/plugins/rules/types' import {TerraformSSHConnection, TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { ApplicationDirectory, - BASH_HEADER, - BashCallManagementOperation, - BashCopyManagementOperation, - BashCreateApplicationDirectory, - BashCreateApplicationEnvironment, - BashCreateVintnerDirectory, - BashDeleteApplicationDirectory, - BashDownloadSourceArchive, - BashUnarchiveSourceArchiveFile, MetadataGenerated, OpenstackMachineCredentials, OpenstackMachineHost, } from '#technologies/plugins/rules/utils/utils' +import * as utils from '#utils' class Generator extends GeneratorAbstract { component = 'software.application' @@ -53,23 +53,33 @@ class Generator extends GeneratorAbstract { provisioner: { file: [ { - content: this.create(name, type), + content: utils.concat([ + BashSoftwareApplicationSourceArchiveCreate({ + name, + type, + artifact: this.artifact, + }), + BashSoftwareApplicationAptPackageCreate(), + ]), destination: `/tmp/create-${name}.sh`, }, { - content: this.configure(), + content: BashSoftwareApplicationConfigure(), destination: `/tmp/configure-${name}.sh`, }, { - content: this.start(), + content: BashSoftwareApplicationStart({assert: false}), destination: `/tmp/start-${name}.sh`, }, { - content: this.stop(), + content: BashSoftwareApplicationStop({assert: false}), destination: `/tmp/stop-${name}.sh`, }, { - content: this.delete(), + content: utils.concat([ + BashSoftwareApplicationDelete(), + BashSoftwareApplicationAptPackageDelete(), + ]), destination: `/tmp/delete-${name}.sh`, }, ], @@ -100,108 +110,6 @@ class Generator extends GeneratorAbstract { }, } } - - private create(name: string, type: NodeType) { - return `${BASH_HEADER} - -# Run setup script -if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - -fi - -# Add apt key -if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg -fi - -# Add apt repository -if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} -fi - -# Update apt cache -apt-get update -y - -# Install dependencies -if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y -fi - -# Install package -{{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - -# Create application directory -${BashCreateApplicationDirectory()} - -# Create application environment -${BashCreateApplicationEnvironment(type)} - -# Download deployment artifact if required -${BashDownloadSourceArchive(name, this.artifact)} - -# Extract deployment artifact -${BashUnarchiveSourceArchiveFile(name, this.artifact)} - -# Create vintner directory -${BashCreateVintnerDirectory()} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} -` - } - - private configure() { - return `${BASH_HEADER} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} -` - } - - private start() { - return `${BASH_HEADER} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.START)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.START)} -` - } - - private stop() { - return `${BASH_HEADER} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.STOP)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.STOP)} -` - } - - private delete() { - return `${BASH_HEADER} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} - -# Delete application directory -${BashDeleteApplicationDirectory()} - -# Uninstall package -apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y -` - } } export default new Generator() diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/index.ts index dfab123584..e5b39e1579 100644 --- a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/index.ts @@ -1,5 +1,3 @@ -import remoteMachine from './remote-machine' +import machine from './machine' -// TODO: local machine - -export default [remoteMachine] +export default [machine] diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/index.ts new file mode 100644 index 0000000000..2e2d177edd --- /dev/null +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/index.ts @@ -0,0 +1,4 @@ +import localMachine from './local-machine' +import remoteMachine from './remote-machine' + +export default [remoteMachine, localMachine] diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts new file mode 100644 index 0000000000..bfccaf0078 --- /dev/null +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts @@ -0,0 +1,129 @@ +import {NodeType} from '#spec/node-type' +import { + AnsibleSoftwareApplicationSourceArchiveConfigure, + AnsibleSoftwareApplicationSourceArchiveCreate, + AnsibleSoftwareApplicationSourceArchiveDelete, + AnsibleSoftwareApplicationSourceArchiveStart, + AnsibleSoftwareApplicationSourceArchiveStop, +} from '#technologies/plugins/rules/generators/software-application/utils' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation, AnsibleWaitForSSHTask} from '#technologies/plugins/rules/utils/ansible' +import {ApplicationDirectory, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' + +class Generator extends GeneratorAbstract { + component = 'software.application' + technology = 'ansible' + artifact = 'tar.archive' + hosting = ['*', 'local.machine'] + weight = 0.5 + reason = + 'While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application.' + details = + '"ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' + + generate(name: string, type: NodeType) { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...ApplicationDirectory(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + { + name: 'install operational dependencies', + 'ansible.builtin.apt': { + name: 'unzip', + update_cache: 'yes', + }, + }, + ...AnsibleSoftwareApplicationSourceArchiveCreate({ + type, + artifact: this.artifact, + }), + ], + }, + }, + }, + configure: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleSoftwareApplicationSourceArchiveConfigure(), + ], + }, + }, + }, + start: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleSoftwareApplicationSourceArchiveStart(), + ], + }, + }, + }, + stop: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleSoftwareApplicationSourceArchiveStop(), + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleSoftwareApplicationSourceArchiveDelete(), + ], + }, + }, + }, + }, + }, + }, + } + } +} + +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/index.ts rename to src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/index.ts diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts new file mode 100644 index 0000000000..5d727e6432 --- /dev/null +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts @@ -0,0 +1,116 @@ +import {NodeType} from '#spec/node-type' +import { + BashSoftwareApplicationConfigure, + BashSoftwareApplicationDelete, + BashSoftwareApplicationSourceArchiveCreate, + BashSoftwareApplicationStart, + BashSoftwareApplicationStop, +} from '#technologies/plugins/rules/generators/software-application/utils' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import { + ApplicationDirectory, + JinjaWhenSourceArchiveFile, + MetadataGenerated, + OpenstackMachineCredentials, + OpenstackMachineHost, + SourceArchiveFile, +} from '#technologies/plugins/rules/utils/utils' + +class Generator extends GeneratorAbstract { + component = 'software.application' + technology = 'terraform' + artifact = 'tar.archive' + hosting = ['*', 'local.machine'] + weight = 0 + reason = 'Ansible is more specialized. Also using provisioners is a "last resort".' + details = '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' + + generate(name: string, type: NodeType) { + return { + derived_from: name, + metadata: {...MetadataGenerated()}, + properties: { + ...OpenstackMachineCredentials(), + ...OpenstackMachineHost(), + ...ApplicationDirectory(), + }, + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + resource: { + local_file: { + tmp_artifact: { + source: SourceArchiveFile(this.artifact), + filename: `/tmp/artifact-${name}`, + count: `{{ (${JinjaWhenSourceArchiveFile(this.artifact)}) | ternary(1, 0) }}`, + }, + tmp_create: { + content: BashSoftwareApplicationSourceArchiveCreate({ + name, + type, + artifact: this.artifact, + }), + filename: `/tmp/create-${name}.sh`, + }, + tmp_configure: { + content: BashSoftwareApplicationConfigure(), + filename: `/tmp/configure-${name}.sh`, + }, + tmp_start: { + content: BashSoftwareApplicationStart(), + filename: `/tmp/start-${name}.sh`, + }, + tmp_stop: { + content: BashSoftwareApplicationStop(), + filename: `/tmp/stop-${name}.sh`, + }, + tmp_delete: { + content: BashSoftwareApplicationDelete(), + filename: `/tmp/delete-${name}.sh`, + }, + }, + terraform_data: { + vm: [ + { + depends_on: [ + 'local_file.tmp_artifact', + 'local_file.tmp_create', + 'local_file.tmp_configure', + 'local_file.tmp_start', + 'local_file.tmp_stop', + 'local_file.tmp_delete', + ], + provisioner: { + 'local-exec': [ + { + inline: [ + `sudo bash /tmp/create-${name}.sh`, + `sudo bash /tmp/configure-${name}.sh`, + `sudo bash /tmp/start-${name}.sh`, + ], + }, + { + inline: [ + `sudo bash /tmp/stop-${name}.sh`, + `sudo bash /tmp/delete-${name}.sh`, + ], + when: 'destroy', + }, + ], + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + } +} + +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/ansible/index.ts new file mode 100644 index 0000000000..2b0718ebf9 --- /dev/null +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/ansible/index.ts @@ -0,0 +1,137 @@ +import {NodeType} from '#spec/node-type' +import { + AnsibleSoftwareApplicationSourceArchiveConfigure, + AnsibleSoftwareApplicationSourceArchiveCreate, + AnsibleSoftwareApplicationSourceArchiveDelete, + AnsibleSoftwareApplicationSourceArchiveStart, + AnsibleSoftwareApplicationSourceArchiveStop, +} from '#technologies/plugins/rules/generators/software-application/utils' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import { + AnsibleHostOperation, + AnsibleHostOperationPlaybookArgs, + AnsibleWaitForSSHTask, +} from '#technologies/plugins/rules/utils/ansible' +import { + ApplicationDirectory, + MetadataGenerated, + MetadataUnfurl, + OpenstackMachineCredentials, +} from '#technologies/plugins/rules/utils/utils' + +class Generator extends GeneratorAbstract { + component = 'software.application' + technology = 'ansible' + artifact = 'tar.archive' + hosting = ['*', 'remote.machine'] + weight = 0.5 + reason = + 'While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application".' + details = + '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' + + generate(name: string, type: NodeType) { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...OpenstackMachineCredentials(), + ...ApplicationDirectory(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleSoftwareApplicationSourceArchiveCreate({ + type, + artifact: this.artifact, + }), + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, + configure: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleSoftwareApplicationSourceArchiveConfigure(), + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, + start: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleSoftwareApplicationSourceArchiveStart(), + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, + stop: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleSoftwareApplicationSourceArchiveStop(), + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, + delete: { + implementation: { + ...AnsibleHostOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleSoftwareApplicationSourceArchiveDelete(), + ], + }, + playbookArgs: [...AnsibleHostOperationPlaybookArgs()], + }, + }, + }, + }, + }, + } + } +} + +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/index.ts rename to src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/index.ts diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/terraform/index.ts similarity index 70% rename from src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/terraform/index.ts rename to src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/terraform/index.ts index 10fed34ded..bd28ce6b46 100644 --- a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/terraform/index.ts @@ -1,19 +1,15 @@ -import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {NodeType} from '#spec/node-type' +import { + BashSoftwareApplicationConfigure, + BashSoftwareApplicationDelete, + BashSoftwareApplicationSourceArchiveCreate, + BashSoftwareApplicationStart, + BashSoftwareApplicationStop, +} from '#technologies/plugins/rules/generators/software-application/utils' import {GeneratorAbstract} from '#technologies/plugins/rules/types' import {TerraformSSHConnection, TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { ApplicationDirectory, - BASH_HEADER, - BashAssertManagementOperation, - BashCallManagementOperation, - BashCopyManagementOperation, - BashCreateApplicationDirectory, - BashCreateApplicationEnvironment, - BashCreateVintnerDirectory, - BashDeleteApplicationDirectory, - BashDownloadSourceArchive, - BashUnarchiveSourceArchiveFile, JinjaWhenSourceArchiveFile, MetadataGenerated, OpenstackMachineCredentials, @@ -63,23 +59,27 @@ class Generator extends GeneratorAbstract { )}) | ternary(1, 0) }}`, }, { - content: this.create(name, type), + content: BashSoftwareApplicationSourceArchiveCreate({ + name, + type, + artifact: this.artifact, + }), destination: `/tmp/create-${name}.sh`, }, { - content: this.configure(), + content: BashSoftwareApplicationConfigure(), destination: `/tmp/configure-${name}.sh`, }, { - content: this.start(), + content: BashSoftwareApplicationStart(), destination: `/tmp/start-${name}.sh`, }, { - content: this.stop(), + content: BashSoftwareApplicationStop(), destination: `/tmp/stop-${name}.sh`, }, { - content: this.delete(), + content: BashSoftwareApplicationDelete(), destination: `/tmp/delete-${name}.sh`, }, ], @@ -110,85 +110,6 @@ class Generator extends GeneratorAbstract { }, } } - - private create(name: string, type: NodeType) { - return `${BASH_HEADER} - -# Create application directory -${BashCreateApplicationDirectory()} - -# Create application environment -${BashCreateApplicationEnvironment(type)} - -# Download deployment artifact if required -${BashDownloadSourceArchive(name, this.artifact)} - -# Extract deployment artifact -${BashUnarchiveSourceArchiveFile(name, this.artifact)} - -# Create vintner directory -${BashCreateVintnerDirectory()} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} -` - } - - private configure() { - return `${BASH_HEADER} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} -` - } - - private start() { - return `${BASH_HEADER} - -# Assert operation -${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.START)} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.START)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.START)} -` - } - - private stop() { - return `${BASH_HEADER} - -# Assert operation -${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.STOP)} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.STOP)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.STOP)} -` - } - - private delete() { - return `${BASH_HEADER} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} - -# Delete application directory -${BashDeleteApplicationDirectory()} -` - } } export default new Generator() diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/ansible/index.ts deleted file mode 100644 index e5fd18e86c..0000000000 --- a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/remote-machine/ansible/index.ts +++ /dev/null @@ -1,186 +0,0 @@ -import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' -import {ImplementationGenerator} from '#technologies/plugins/rules/types' -import { - AnsibleAssertOperationTask, - AnsibleCallManagementOperationTask, - AnsibleCopyManagementOperationTask, - AnsibleCreateApplicationDirectoryTask, - AnsibleCreateApplicationEnvironment, - AnsibleCreateVintnerDirectory, - AnsibleDeleteApplicationDirectoryTask, - AnsibleHostOperation, - AnsibleHostOperationPlaybookArgs, - AnsibleUnarchiveSourceArchiveFileTask, - AnsibleUnarchiveSourceArchiveUrlTask, - AnsibleWaitForSSHTask, -} from '#technologies/plugins/rules/utils/ansible' -import { - ApplicationDirectory, - MetadataGenerated, - MetadataUnfurl, - OpenstackMachineCredentials, -} from '#technologies/plugins/rules/utils/utils' - -const artifact = 'tar.archive' - -const generator: ImplementationGenerator = { - component: 'software.application', - technology: 'ansible', - artifact, - hosting: ['*', 'remote.machine'], - weight: 0.5, - reason: 'While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application".', - details: - '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements', - - generate: (name, type) => { - return { - derived_from: name, - metadata: { - ...MetadataGenerated(), - ...MetadataUnfurl(), - }, - properties: { - ...OpenstackMachineCredentials(), - ...ApplicationDirectory(), - }, - interfaces: { - Standard: { - operations: { - create: { - implementation: { - ...AnsibleHostOperation(), - }, - inputs: { - playbook: { - q: [ - { - ...AnsibleWaitForSSHTask(), - }, - { - ...AnsibleCreateApplicationDirectoryTask(), - }, - { - ...AnsibleUnarchiveSourceArchiveFileTask(artifact), - }, - { - ...AnsibleUnarchiveSourceArchiveUrlTask(artifact), - }, - { - ...AnsibleCreateVintnerDirectory(), - }, - { - ...AnsibleCreateApplicationEnvironment(type), - }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), - }, - ], - }, - playbookArgs: [...AnsibleHostOperationPlaybookArgs()], - }, - }, - configure: { - implementation: { - ...AnsibleHostOperation(), - }, - inputs: { - playbook: { - q: [ - { - ...AnsibleWaitForSSHTask(), - }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), - }, - ], - }, - playbookArgs: [...AnsibleHostOperationPlaybookArgs()], - }, - }, - start: { - implementation: { - ...AnsibleHostOperation(), - }, - inputs: { - playbook: { - q: [ - { - ...AnsibleWaitForSSHTask(), - }, - { - ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.START), - }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.START), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.START), - }, - ], - }, - playbookArgs: [...AnsibleHostOperationPlaybookArgs()], - }, - }, - stop: { - implementation: { - ...AnsibleHostOperation(), - }, - inputs: { - playbook: { - q: [ - { - ...AnsibleWaitForSSHTask(), - }, - { - ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.STOP), - }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), - }, - ], - }, - playbookArgs: [...AnsibleHostOperationPlaybookArgs()], - }, - }, - delete: { - implementation: { - ...AnsibleHostOperation(), - }, - inputs: { - playbook: { - q: [ - { - ...AnsibleWaitForSSHTask(), - }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), - }, - { - ...AnsibleDeleteApplicationDirectoryTask(), - }, - ], - }, - playbookArgs: [...AnsibleHostOperationPlaybookArgs()], - }, - }, - }, - }, - }, - } - }, -} - -export default generator diff --git a/src/technologies/plugins/rules/generators/software-application/utils.ts b/src/technologies/plugins/rules/generators/software-application/utils.ts new file mode 100644 index 0000000000..f141fe4cf1 --- /dev/null +++ b/src/technologies/plugins/rules/generators/software-application/utils.ts @@ -0,0 +1,230 @@ +import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' +import {NodeType} from '#spec/node-type' +import { + AnsibleAssertOperationTask, + AnsibleCallManagementOperationTask, + AnsibleCopyManagementOperationTask, + AnsibleCreateApplicationDirectoryTask, + AnsibleCreateApplicationEnvironment, + AnsibleCreateVintnerDirectory, + AnsibleDeleteApplicationDirectoryTask, + AnsibleUnarchiveSourceArchiveFileTask, + AnsibleUnarchiveSourceArchiveUrlTask, +} from '#technologies/plugins/rules/utils/ansible' +import { + BASH_HEADER, + BashAssertManagementOperation, + BashCallManagementOperation, + BashCopyManagementOperation, + BashCreateApplicationDirectory, + BashCreateApplicationEnvironment, + BashCreateVintnerDirectory, + BashDeleteApplicationDirectory, + BashDownloadSourceArchive, + BashUnarchiveSourceArchiveFile, +} from '#technologies/plugins/rules/utils/utils' +import * as utils from '#utils' + +export function AnsibleSoftwareApplicationSourceArchiveCreate(options: {artifact: string; type: NodeType}) { + return [ + { + ...AnsibleCreateApplicationDirectoryTask(), + }, + { + ...AnsibleUnarchiveSourceArchiveFileTask(options.artifact), + }, + { + ...AnsibleUnarchiveSourceArchiveUrlTask(options.artifact), + }, + { + ...AnsibleCreateVintnerDirectory(), + }, + { + ...AnsibleCreateApplicationEnvironment(options.type), + }, + { + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), + }, + { + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), + }, + ] +} + +export function AnsibleSoftwareApplicationSourceArchiveConfigure() { + return [ + { + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), + }, + { + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), + }, + ] +} + +export function AnsibleSoftwareApplicationSourceArchiveStart() { + return [ + { + ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.START), + }, + { + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.START), + }, + { + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.START), + }, + ] +} + +export function AnsibleSoftwareApplicationSourceArchiveStop() { + return [ + { + ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.STOP), + }, + { + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), + }, + { + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), + }, + ] +} + +export function AnsibleSoftwareApplicationSourceArchiveDelete() { + return [ + { + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), + }, + { + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), + }, + { + ...AnsibleDeleteApplicationDirectoryTask(), + }, + ] +} + +export function BashSoftwareApplicationSourceArchiveCreate(options: {name: string; type: NodeType; artifact: string}) { + return utils.trim(` +${BASH_HEADER} + +# Create application directory +${BashCreateApplicationDirectory()} + +# Create application environment +${BashCreateApplicationEnvironment(options.type)} + +# Download deployment artifact if required +${BashDownloadSourceArchive(options.name, options.artifact)} + +# Extract deployment artifact +${BashUnarchiveSourceArchiveFile(options.name, options.artifact)} + +# Create vintner directory +${BashCreateVintnerDirectory()} + +# Copy operation +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} + +# Execute operation +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} +`) +} + +export function BashSoftwareApplicationConfigure() { + return utils.trim(` +${BASH_HEADER} + +# Copy operation +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} + +# Execute operation +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} +`) +} + +// TODO: assert +export function BashSoftwareApplicationStart(options: {assert?: boolean} = {}) { + options.assert = options.assert ?? true + + return utils.trim(` +${BASH_HEADER} + +# Assert operation +${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.START)} + +# Copy operation +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.START)} + +# Execute operation +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.START)} +`) +} + +// TODO: assert +export function BashSoftwareApplicationStop(options: {assert?: boolean} = {}) { + return utils.trim(` +${BASH_HEADER} + +# Assert operation +${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.STOP)} + +# Copy operation +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.STOP)} + +# Execute operation +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.STOP)} +`) +} + +export function BashSoftwareApplicationDelete() { + return utils.trim(` +${BASH_HEADER} + +# Copy operation +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} + +# Execute operation +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} + +# Delete application directory +${BashDeleteApplicationDirectory()} +`) +} + +export function BashSoftwareApplicationAptPackageCreate() { + return utils.trim(` +# Run setup script +if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then + curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - +fi + +# Add apt key +if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then + curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg +fi + +# Add apt repository +if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then + echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} +fi + +# Update apt cache +apt-get update -y + +# Install dependencies +if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then + apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y +fi + +# Install package +{{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y +`) +} + +export function BashSoftwareApplicationAptPackageDelete() { + return utils.trim(` +# Uninstall package +apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y +`) +} diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/index.ts index dfab123584..e5b39e1579 100644 --- a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/index.ts @@ -1,5 +1,3 @@ -import remoteMachine from './remote-machine' +import machine from './machine' -// TODO: local machine - -export default [remoteMachine] +export default [machine] diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/index.ts new file mode 100644 index 0000000000..2e2d177edd --- /dev/null +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/index.ts @@ -0,0 +1,4 @@ +import localMachine from './local-machine' +import remoteMachine from './remote-machine' + +export default [remoteMachine, localMachine] diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts new file mode 100644 index 0000000000..046118315c --- /dev/null +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts @@ -0,0 +1,129 @@ +import {NodeType} from '#spec/node-type' +import { + AnsibleSoftwareApplicationSourceArchiveConfigure, + AnsibleSoftwareApplicationSourceArchiveCreate, + AnsibleSoftwareApplicationSourceArchiveDelete, + AnsibleSoftwareApplicationSourceArchiveStart, + AnsibleSoftwareApplicationSourceArchiveStop, +} from '#technologies/plugins/rules/generators/software-application/utils' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation, AnsibleWaitForSSHTask} from '#technologies/plugins/rules/utils/ansible' +import {ApplicationDirectory, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' + +class Generator extends GeneratorAbstract { + component = 'software.application' + technology = 'ansible' + artifact = 'zip.archive' + hosting = ['*', 'local.machine'] + weight = 0.5 + reason = + 'While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application.' + details = + '"ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' + + generate(name: string, type: NodeType) { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...ApplicationDirectory(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + { + name: 'install operational dependencies', + 'ansible.builtin.apt': { + name: 'unzip', + update_cache: 'yes', + }, + }, + ...AnsibleSoftwareApplicationSourceArchiveCreate({ + type, + artifact: this.artifact, + }), + ], + }, + }, + }, + configure: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleSoftwareApplicationSourceArchiveConfigure(), + ], + }, + }, + }, + start: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleSoftwareApplicationSourceArchiveStart(), + ], + }, + }, + }, + stop: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleSoftwareApplicationSourceArchiveStop(), + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + ...AnsibleWaitForSSHTask(), + }, + ...AnsibleSoftwareApplicationSourceArchiveDelete(), + ], + }, + }, + }, + }, + }, + }, + } + } +} + +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/index.ts new file mode 100644 index 0000000000..c76a810960 --- /dev/null +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/index.ts @@ -0,0 +1,4 @@ +import ansible from './ansible' +import terraform from './terraform' + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts new file mode 100644 index 0000000000..edea24a178 --- /dev/null +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts @@ -0,0 +1,116 @@ +import {NodeType} from '#spec/node-type' +import { + BashSoftwareApplicationConfigure, + BashSoftwareApplicationDelete, + BashSoftwareApplicationSourceArchiveCreate, + BashSoftwareApplicationStart, + BashSoftwareApplicationStop, +} from '#technologies/plugins/rules/generators/software-application/utils' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import { + ApplicationDirectory, + JinjaWhenSourceArchiveFile, + MetadataGenerated, + OpenstackMachineCredentials, + OpenstackMachineHost, + SourceArchiveFile, +} from '#technologies/plugins/rules/utils/utils' + +class Generator extends GeneratorAbstract { + component = 'software.application' + technology = 'terraform' + artifact = 'zip.archive' + hosting = ['*', 'local.machine'] + weight = 0 + reason = 'Ansible is more specialized. Also using provisioners is a "last resort".' + details = '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' + + generate(name: string, type: NodeType) { + return { + derived_from: name, + metadata: {...MetadataGenerated()}, + properties: { + ...OpenstackMachineCredentials(), + ...OpenstackMachineHost(), + ...ApplicationDirectory(), + }, + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + resource: { + local_file: { + tmp_artifact: { + source: SourceArchiveFile(this.artifact), + filename: `/tmp/artifact-${name}`, + count: `{{ (${JinjaWhenSourceArchiveFile(this.artifact)}) | ternary(1, 0) }}`, + }, + tmp_create: { + content: BashSoftwareApplicationSourceArchiveCreate({ + name, + type, + artifact: this.artifact, + }), + filename: `/tmp/create-${name}.sh`, + }, + tmp_configure: { + content: BashSoftwareApplicationConfigure(), + filename: `/tmp/configure-${name}.sh`, + }, + tmp_start: { + content: BashSoftwareApplicationStart(), + filename: `/tmp/start-${name}.sh`, + }, + tmp_stop: { + content: BashSoftwareApplicationStop(), + filename: `/tmp/stop-${name}.sh`, + }, + tmp_delete: { + content: BashSoftwareApplicationDelete(), + filename: `/tmp/delete-${name}.sh`, + }, + }, + terraform_data: { + vm: [ + { + depends_on: [ + 'local_file.tmp_artifact', + 'local_file.tmp_create', + 'local_file.tmp_configure', + 'local_file.tmp_start', + 'local_file.tmp_stop', + 'local_file.tmp_delete', + ], + provisioner: { + 'local-exec': [ + { + inline: [ + `sudo bash /tmp/create-${name}.sh`, + `sudo bash /tmp/configure-${name}.sh`, + `sudo bash /tmp/start-${name}.sh`, + ], + }, + { + inline: [ + `sudo bash /tmp/stop-${name}.sh`, + `sudo bash /tmp/delete-${name}.sh`, + ], + when: 'destroy', + }, + ], + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + } +} + +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/ansible/index.ts similarity index 51% rename from src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/ansible/index.ts rename to src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/ansible/index.ts index b214c17051..3190ba73a4 100644 --- a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/ansible/index.ts @@ -1,16 +1,15 @@ -import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' -import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {NodeType} from '#spec/node-type' +import { + AnsibleSoftwareApplicationSourceArchiveConfigure, + AnsibleSoftwareApplicationSourceArchiveCreate, + AnsibleSoftwareApplicationSourceArchiveDelete, + AnsibleSoftwareApplicationSourceArchiveStart, + AnsibleSoftwareApplicationSourceArchiveStop, +} from '#technologies/plugins/rules/generators/software-application/utils' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' import { - AnsibleAssertOperationTask, - AnsibleCallManagementOperationTask, - AnsibleCopyManagementOperationTask, - AnsibleCreateApplicationDirectoryTask, - AnsibleCreateApplicationEnvironment, - AnsibleCreateVintnerDirectory, - AnsibleDeleteApplicationDirectoryTask, AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, - AnsibleUnarchiveSourceArchiveFileTask, AnsibleWaitForSSHTask, } from '#technologies/plugins/rules/utils/ansible' import { @@ -20,19 +19,18 @@ import { OpenstackMachineCredentials, } from '#technologies/plugins/rules/utils/utils' -const artifact = 'zip.archive' - -const generator: ImplementationGenerator = { - component: 'software.application', - technology: 'ansible', - artifact, - hosting: ['*', 'remote.machine'], - weight: 0.5, - reason: 'While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application.', - details: - '"ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements', +class Generator extends GeneratorAbstract { + component = 'software.application' + technology = 'ansible' + artifact = 'zip.archive' + hosting = ['*', 'remote.machine'] + weight = 0.5 + reason = + 'While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application.' + details = + '"ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' - generate: (name, type) => { + generate(name: string, type: NodeType) { return { derived_from: name, metadata: { @@ -63,27 +61,10 @@ const generator: ImplementationGenerator = { update_cache: 'yes', }, }, - { - ...AnsibleCreateApplicationDirectoryTask(), - }, - { - ...AnsibleUnarchiveSourceArchiveFileTask(artifact), - }, - { - ...AnsibleUnarchiveSourceArchiveFileTask(artifact), - }, - { - ...AnsibleCreateVintnerDirectory(), - }, - { - ...AnsibleCreateApplicationEnvironment(type), - }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), - }, + ...AnsibleSoftwareApplicationSourceArchiveCreate({ + type, + artifact: this.artifact, + }), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -99,12 +80,7 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), - }, + ...AnsibleSoftwareApplicationSourceArchiveConfigure(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -120,15 +96,7 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, - { - ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.START), - }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.START), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.START), - }, + ...AnsibleSoftwareApplicationSourceArchiveStart(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -144,15 +112,7 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, - { - ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.STOP), - }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), - }, + ...AnsibleSoftwareApplicationSourceArchiveStop(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -168,15 +128,7 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), - }, - { - ...AnsibleDeleteApplicationDirectoryTask(), - }, + ...AnsibleSoftwareApplicationSourceArchiveDelete(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -186,7 +138,7 @@ const generator: ImplementationGenerator = { }, }, } - }, + } } -export default generator +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/index.ts new file mode 100644 index 0000000000..c76a810960 --- /dev/null +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/index.ts @@ -0,0 +1,4 @@ +import ansible from './ansible' +import terraform from './terraform' + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/terraform/index.ts similarity index 69% rename from src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/terraform/index.ts rename to src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/terraform/index.ts index 4e550ce67a..0431044bf7 100644 --- a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/terraform/index.ts @@ -1,19 +1,15 @@ -import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {NodeType} from '#spec/node-type' +import { + BashSoftwareApplicationConfigure, + BashSoftwareApplicationDelete, + BashSoftwareApplicationSourceArchiveCreate, + BashSoftwareApplicationStart, + BashSoftwareApplicationStop, +} from '#technologies/plugins/rules/generators/software-application/utils' import {GeneratorAbstract} from '#technologies/plugins/rules/types' import {TerraformSSHConnection, TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { ApplicationDirectory, - BASH_HEADER, - BashAssertManagementOperation, - BashCallManagementOperation, - BashCopyManagementOperation, - BashCreateApplicationDirectory, - BashCreateApplicationEnvironment, - BashCreateVintnerDirectory, - BashDeleteApplicationDirectory, - BashDownloadSourceArchive, - BashUnarchiveSourceArchiveFile, JinjaWhenSourceArchiveFile, MetadataGenerated, OpenstackMachineCredentials, @@ -21,7 +17,7 @@ import { SourceArchiveFile, } from '#technologies/plugins/rules/utils/utils' -export class Generator extends GeneratorAbstract { +class Generator extends GeneratorAbstract { component = 'software.application' technology = 'terraform' artifact = 'zip.archive' @@ -63,23 +59,27 @@ export class Generator extends GeneratorAbstract { )}) | ternary(1, 0) }}`, }, { - content: this.create(name, type), + content: BashSoftwareApplicationSourceArchiveCreate({ + name, + type, + artifact: this.artifact, + }), destination: `/tmp/create-${name}.sh`, }, { - content: this.configure(), + content: BashSoftwareApplicationConfigure(), destination: `/tmp/configure-${name}.sh`, }, { - content: this.start(), + content: BashSoftwareApplicationStart(), destination: `/tmp/start-${name}.sh`, }, { - content: this.stop(), + content: BashSoftwareApplicationStop(), destination: `/tmp/stop-${name}.sh`, }, { - content: this.delete(), + content: BashSoftwareApplicationDelete(), destination: `/tmp/delete-${name}.sh`, }, ], @@ -110,85 +110,6 @@ export class Generator extends GeneratorAbstract { }, } } - - private create(name: string, type: NodeType) { - return `${BASH_HEADER} - -# Create application directory -${BashCreateApplicationDirectory()} - -# Create application environment -${BashCreateApplicationEnvironment(type)} - -# Download deployment artifact if required -${BashDownloadSourceArchive(name, this.artifact)} - -# Extract deployment artifact -${BashUnarchiveSourceArchiveFile(name, this.artifact)} - -# Create vintner directory -${BashCreateVintnerDirectory()} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} -` - } - - private configure() { - return `${BASH_HEADER} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} -` - } - - private start() { - return `${BASH_HEADER} - -# Assert operation -${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.START)} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.START)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.START)} -` - } - - private stop() { - return `${BASH_HEADER} - -# Assert operation -${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.STOP)} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.STOP)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.STOP)} -` - } - - private delete() { - return `${BASH_HEADER} - -# Copy operation -${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} - -# Execute operation -${BashCallManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} - -# Delete application directory -${BashDeleteApplicationDirectory()} -` - } } export default new Generator() diff --git a/src/utils/utils.ts b/src/utils/utils.ts index bd557740ba..1afdebff5d 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -228,3 +228,7 @@ export function indent(value: string, spaces = 4) { export function trim(value: string): string { return value.trim() + `\n` } + +export function concat(values: string[]) { + return values.join(`\n`) +} From 806293dc7b23279a8f2f9232aa74e5baea04009d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Sun, 8 Sep 2024 13:21:54 +0200 Subject: [PATCH 10/18] continue --- docs/docs/variability4tosca/rules/index.md | 238 +++++++++++++++--- .../rules/technology-rules.yaml | 70 ++++++ .../machine/local-machine/ansible/index.ts | 99 ++++++++ .../asterisk/machine/local-machine/index.ts | 4 + .../machine/local-machine/terraform/index.ts | 114 +++++++++ .../machine/remote-machine/ansible/index.ts | 89 +------ .../machine/remote-machine/terraform/index.ts | 14 +- .../machine/local-machine/ansible/index.ts | 16 +- .../machine/local-machine/terraform/index.ts | 2 +- .../machine/remote-machine/ansible/index.ts | 16 +- .../generators/software-application/utils.ts | 100 +++++++- .../machine/local-machine/ansible/index.ts | 16 +- .../machine/local-machine/terraform/index.ts | 2 +- .../machine/remote-machine/ansible/index.ts | 16 +- 14 files changed, 634 insertions(+), 162 deletions(-) create mode 100644 src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/terraform/index.ts diff --git a/docs/docs/variability4tosca/rules/index.md b/docs/docs/variability4tosca/rules/index.md index bf5c45b041..1e555c3f7d 100644 --- a/docs/docs/variability4tosca/rules/index.md +++ b/docs/docs/variability4tosca/rules/index.md @@ -419,6 +419,23 @@ The node template is hosted on the node template "host 1" of node type [kubernet ### Scenario #5 +In this scenario, the node template "component" of node type [mysql.dbms](/normative#mysqldbms){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [dbms.image](/normative#dbmsimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(mysql.dbms)artifact(dbms.image)host 1(local.machine)host
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! failure "Terraform (Quality: 0)" + Ansible is more specialized. Also using provisioners is a "last resort". + + + +### Scenario #6 + In this scenario, the node template "component" of node type [mysql.dbms](/normative#mysqldbms){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [dbms.image](/normative#dbmsimage){target=_blank}. The node template is hosted on the node template "host 1" of node type [remote.machine](/normative#remotemachine){target=_blank}. @@ -678,6 +695,23 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w ### Scenario #3 +In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [apt.package](/normative#aptpackage){target=_blank}. +The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(software.application)artifact(apt.package)...host 2(local.machine)hosthost
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! failure "Terraform (Quality: 0)" + Ansible is more specialized. Also using provisioners is a "last resort". + + + +### Scenario #4 + In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [tar.archive](/normative#tararchive){target=_blank}. The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. @@ -693,7 +727,24 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w -### Scenario #4 +### Scenario #5 + +In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [tar.archive](/normative#tararchive){target=_blank}. +The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(software.application)artifact(tar.archive)...host 2(local.machine)hosthost
+ + +!!! info "Ansible (Quality: 0.5)" + While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. + +!!! failure "Terraform (Quality: 0)" + Ansible is more specialized. Also using provisioners is a "last resort". + + + +### Scenario #6 In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [zip.archive](/normative#ziparchive){target=_blank}. @@ -710,6 +761,23 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w +### Scenario #7 + +In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [zip.archive](/normative#ziparchive){target=_blank}. +The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(software.application)artifact(zip.archive)...host 2(local.machine)hosthost
+ + +!!! info "Ansible (Quality: 0.5)" + While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. + +!!! failure "Terraform (Quality: 0)" + Ansible is more specialized. Also using provisioners is a "last resort". + + + ## Component "virtual.machine" The following scenarios deploy a node template of node type [virtual.machine](/normative#virtualmachine){target=_blank} with various hosting stacks, artifacts, deployment technologies, and qualities. @@ -1222,6 +1290,30 @@ This appendix contains the deployment technology rules. ### Rule #44 | Attribute | Value | | --- | --- | +| Identifier | mysql.dbms#dbms.image::ansible@local.machine | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | "ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(local.machine)host
| + +### Rule #45 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.dbms#dbms.image::terraform@local.machine | +| Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | +| Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Hosting | [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0 | +| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | +| Details | "terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner | +| Graph |
component(mysql.dbms)artifact(dbms.image)host 1(local.machine)host
| + +### Rule #46 +| Attribute | Value | +| --- | --- | | Identifier | mysql.dbms#dbms.image::ansible@remote.machine | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | @@ -1231,7 +1323,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(remote.machine)host
| -### Rule #45 +### Rule #47 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::terraform@remote.machine | @@ -1243,7 +1335,7 @@ This appendix contains the deployment technology rules. | Details | "terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(remote.machine)host
| -### Rule #46 +### Rule #48 | Attribute | Value | | --- | --- | | Identifier | bucket#cache.image::ansible@gcp.memorystore | @@ -1255,7 +1347,7 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(bucket)artifact(cache.image)host 1(gcp.memorystore)host
| -### Rule #47 +### Rule #49 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::terraform@gcp.memorystore | @@ -1267,7 +1359,7 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(redis.server)artifact(cache.image)host 1(gcp.memorystore)host
| -### Rule #48 +### Rule #50 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::ansible@docker.engine->local.machine | @@ -1279,7 +1371,7 @@ This appendix contains the deployment technology rules. | Details | "community.docker.docker_container" task | | Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #49 +### Rule #51 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::compose@docker.engine->local.machine | @@ -1291,7 +1383,7 @@ This appendix contains the deployment technology rules. | Details | docker compose manifest generated and applied | | Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #50 +### Rule #52 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::terraform@docker.engine->local.machine | @@ -1303,7 +1395,7 @@ This appendix contains the deployment technology rules. | Details | "docker_container" and "docker_image" resources | | Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #51 +### Rule #53 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::ansible@docker.engine->remote.machine | @@ -1315,7 +1407,7 @@ This appendix contains the deployment technology rules. | Details | "community.docker.docker_container" task | | Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #52 +### Rule #54 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::compose@docker.engine->remote.machine | @@ -1327,7 +1419,7 @@ This appendix contains the deployment technology rules. | Details | docker compose manifest generated and applied | | Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #53 +### Rule #55 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::terraform@docker.engine->remote.machine | @@ -1339,7 +1431,7 @@ This appendix contains the deployment technology rules. | Details | "docker_container" and "docker_image" resources | | Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #54 +### Rule #56 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::ansible@kubernetes.cluster | @@ -1351,7 +1443,7 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(redis.server)artifact(cache.image)host 1(kubernetes.cluster)host
| -### Rule #55 +### Rule #57 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::terraform@kubernetes.cluster | @@ -1363,7 +1455,7 @@ This appendix contains the deployment technology rules. | Details | | | Graph |
component(redis.server)artifact(cache.image)host 1(kubernetes.cluster)host
| -### Rule #56 +### Rule #58 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::ansible@docker.engine->local.machine | @@ -1375,7 +1467,7 @@ This appendix contains the deployment technology rules. | Details | "community.docker.docker_container" task | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #57 +### Rule #59 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::compose@docker.engine->local.machine | @@ -1387,7 +1479,7 @@ This appendix contains the deployment technology rules. | Details | docker compose manifest generated and applied | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #58 +### Rule #60 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::terraform@docker.engine->local.machine | @@ -1399,7 +1491,7 @@ This appendix contains the deployment technology rules. | Details | "docker_container" and "docker_image" resources | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #59 +### Rule #61 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::ansible@docker.engine->remote.machine | @@ -1411,7 +1503,7 @@ This appendix contains the deployment technology rules. | Details | "community.docker.docker_container" task | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #60 +### Rule #62 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::compose@docker.engine->remote.machine | @@ -1423,7 +1515,7 @@ This appendix contains the deployment technology rules. | Details | docker compose manifest generated and applied | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #61 +### Rule #63 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::terraform@docker.engine->remote.machine | @@ -1435,7 +1527,7 @@ This appendix contains the deployment technology rules. | Details | "docker_container" and "docker_image" resources | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #62 +### Rule #64 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::ansible@gcp.cloudrun | @@ -1447,7 +1539,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.shell", "ansible.builtin.tempfile", and "ansible.builtin.copy" tasks | | Graph |
component(service.application)artifact(docker.image)host 1(gcp.cloudrun)host
| -### Rule #63 +### Rule #65 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::terraform@gcp.cloudrun | @@ -1459,7 +1551,7 @@ This appendix contains the deployment technology rules. | Details | "google_cloud_run_v2_service" and "google_cloud_run_service_iam_binding" resources | | Graph |
component(service.application)artifact(docker.image)host 1(gcp.cloudrun)host
| -### Rule #64 +### Rule #66 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::ansible@kubernetes.cluster | @@ -1471,7 +1563,7 @@ This appendix contains the deployment technology rules. | Details | "kubernetes.core.k8s" tasks | | Graph |
component(service.application)artifact(docker.image)host 1(kubernetes.cluster)host
| -### Rule #65 +### Rule #67 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::kubernetes@kubernetes.cluster | @@ -1483,7 +1575,7 @@ This appendix contains the deployment technology rules. | Details | Kubernetes manifest generated and applied | | Graph |
component(service.application)artifact(docker.image)host 1(kubernetes.cluster)host
| -### Rule #66 +### Rule #68 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::terraform@kubernetes.cluster | @@ -1495,7 +1587,7 @@ This appendix contains the deployment technology rules. | Details | "kubernetes_deployment_v1" and "kubernetes_service_v1" resources | | Graph |
component(service.application)artifact(docker.image)host 1(kubernetes.cluster)host
| -### Rule #67 +### Rule #69 | Attribute | Value | | --- | --- | | Identifier | service.application#tar.archive::ansible@*->remote.machine | @@ -1507,7 +1599,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements | | Graph |
component(service.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #68 +### Rule #70 | Attribute | Value | | --- | --- | | Identifier | service.application#tar.archive::terraform@*->remote.machine | @@ -1519,7 +1611,7 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(service.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #69 +### Rule #71 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::ansible@*->remote.machine | @@ -1531,7 +1623,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements | | Graph |
component(service.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #70 +### Rule #72 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::terraform@*->remote.machine | @@ -1543,7 +1635,7 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(service.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #71 +### Rule #73 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::ansible@gcp.appengine | @@ -1555,7 +1647,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.shell", "ansible.builtin.tempfile", "ansible.builtin.unarchive", and "ansible.builtin.copy" tasks | | Graph |
component(service.application)artifact(zip.archive)host 1(gcp.appengine)host
| -### Rule #72 +### Rule #74 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::terraform@gcp.appengine | @@ -1567,7 +1659,7 @@ This appendix contains the deployment technology rules. | Details | "google_app_engine_standard_app_version", "google_project_iam_member", "google_service_account", "google_storage_bucket", and "google_storage_bucket_object" resources | | Graph |
component(service.application)artifact(zip.archive)host 1(gcp.appengine)host
| -### Rule #73 +### Rule #75 | Attribute | Value | | --- | --- | | Identifier | software.application#apt.package::ansible@*->remote.machine | @@ -1579,7 +1671,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements | | Graph |
component(software.application)artifact(apt.package)...host 2(remote.machine)hosthost
| -### Rule #74 +### Rule #76 | Attribute | Value | | --- | --- | | Identifier | software.application#apt.archive::terraform@*->remote.machine | @@ -1591,7 +1683,31 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload scripts and "remote-exec" to execute scripts | | Graph |
component(software.application)artifact(apt.archive)...host 2(remote.machine)hosthost
| -### Rule #75 +### Rule #77 +| Attribute | Value | +| --- | --- | +| Identifier | software.application#apt.package::ansible@*->local.machine | +| Component | [software.application](/normative#softwareapplication){target=_blank} | +| Artifact | [apt.package](/normative#aptpackage){target=_blank} | +| Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | "ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements | +| Graph |
component(software.application)artifact(apt.package)...host 2(local.machine)hosthost
| + +### Rule #78 +| Attribute | Value | +| --- | --- | +| Identifier | software.application#apt.package::terraform@*->local.machine | +| Component | [software.application](/normative#softwareapplication){target=_blank} | +| Artifact | [apt.package](/normative#aptpackage){target=_blank} | +| Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0 | +| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | +| Details | "local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts | +| Graph |
component(software.application)artifact(apt.package)...host 2(local.machine)hosthost
| + +### Rule #79 | Attribute | Value | | --- | --- | | Identifier | software.application#tar.archive::ansible@*->remote.machine | @@ -1603,7 +1719,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | | Graph |
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #76 +### Rule #80 | Attribute | Value | | --- | --- | | Identifier | software.application#tar.archive::terraform@*->remote.machine | @@ -1615,7 +1731,31 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #77 +### Rule #81 +| Attribute | Value | +| --- | --- | +| Identifier | software.application#tar.archive::ansible@*->local.machine | +| Component | [software.application](/normative#softwareapplication){target=_blank} | +| Artifact | [tar.archive](/normative#tararchive){target=_blank} | +| Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. | +| Details | "ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | +| Graph |
component(software.application)artifact(tar.archive)...host 2(local.machine)hosthost
| + +### Rule #82 +| Attribute | Value | +| --- | --- | +| Identifier | software.application#tar.archive::terraform@*->local.machine | +| Component | [software.application](/normative#softwareapplication){target=_blank} | +| Artifact | [tar.archive](/normative#tararchive){target=_blank} | +| Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0 | +| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | +| Details | "local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts | +| Graph |
component(software.application)artifact(tar.archive)...host 2(local.machine)hosthost
| + +### Rule #83 | Attribute | Value | | --- | --- | | Identifier | software.application#zip.archive::ansible@*->remote.machine | @@ -1627,7 +1767,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | | Graph |
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #78 +### Rule #84 | Attribute | Value | | --- | --- | | Identifier | software.application#zip.archive::terraform@*->remote.machine | @@ -1639,7 +1779,31 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #79 +### Rule #85 +| Attribute | Value | +| --- | --- | +| Identifier | software.application#zip.archive::ansible@*->local.machine | +| Component | [software.application](/normative#softwareapplication){target=_blank} | +| Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0.5 | +| Reason | While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. | +| Details | "ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | +| Graph |
component(software.application)artifact(zip.archive)...host 2(local.machine)hosthost
| + +### Rule #86 +| Attribute | Value | +| --- | --- | +| Identifier | software.application#zip.archive::terraform@*->local.machine | +| Component | [software.application](/normative#softwareapplication){target=_blank} | +| Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0 | +| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | +| Details | "local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts | +| Graph |
component(software.application)artifact(zip.archive)...host 2(local.machine)hosthost
| + +### Rule #87 | Attribute | Value | | --- | --- | | Identifier | virtual.machine#machine.image::ansible@openstack.provider | @@ -1651,7 +1815,7 @@ This appendix contains the deployment technology rules. | Details | "openstack.cloud.security_group", "openstack.cloud.security_group_rule" and "openstack.cloud.server" tasks | | Graph |
component(virtual.machine)artifact(machine.image)host 1(openstack.provider)host
| -### Rule #80 +### Rule #88 | Attribute | Value | | --- | --- | | Identifier | virtual.machine#machine.image::terraform@openstack.provider | diff --git a/docs/docs/variability4tosca/rules/technology-rules.yaml b/docs/docs/variability4tosca/rules/technology-rules.yaml index ef6540afa3..0b864074d1 100644 --- a/docs/docs/variability4tosca/rules/technology-rules.yaml +++ b/docs/docs/variability4tosca/rules/technology-rules.yaml @@ -322,6 +322,22 @@ weight: 0.5 reason: Kubernetes is more specialized. details: '"kubernetes_deployment_v1" and "kubernetes_service_v1" resources' +- technology: ansible + component: mysql.dbms + artifact: dbms.image + hosting: + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks' +- technology: terraform + component: mysql.dbms + artifact: dbms.image + hosting: + - local.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' - technology: ansible component: mysql.dbms artifact: dbms.image @@ -584,6 +600,24 @@ weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". details: '"file" provisioner to upload scripts and "remote-exec" to execute scripts' +- technology: ansible + component: software.application + artifact: apt.package + hosting: + - '*' + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements' +- technology: terraform + component: software.application + artifact: apt.package + hosting: + - '*' + - local.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts' - technology: ansible component: software.application artifact: tar.archive @@ -602,6 +636,24 @@ weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' +- technology: ansible + component: software.application + artifact: tar.archive + hosting: + - '*' + - local.machine + weight: 0.5 + reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. + details: '"ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' +- technology: terraform + component: software.application + artifact: tar.archive + hosting: + - '*' + - local.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts' - technology: ansible component: software.application artifact: zip.archive @@ -620,6 +672,24 @@ weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' +- technology: ansible + component: software.application + artifact: zip.archive + hosting: + - '*' + - local.machine + weight: 0.5 + reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. + details: '"ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' +- technology: terraform + component: software.application + artifact: zip.archive + hosting: + - '*' + - local.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts' - technology: ansible component: virtual.machine artifact: machine.image diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/ansible/index.ts new file mode 100644 index 0000000000..9396975642 --- /dev/null +++ b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/ansible/index.ts @@ -0,0 +1,99 @@ +import {NodeType} from '#spec/node-type' +import { + AnsibleSoftwareApplicationAptPackageCreateTasks, + AnsibleSoftwareApplicationAptPackageDeleteTask, + AnsibleSoftwareApplicationConfigureTasks, + AnsibleSoftwareApplicationDeleteTasks, + AnsibleSoftwareApplicationStartTasks, + AnsibleSoftwareApplicationStopTasks, +} from '#technologies/plugins/rules/generators/software-application/utils' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {ApplicationDirectory, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' + +class Generator extends GeneratorAbstract { + component = 'software.application' + technology = 'ansible' + artifact = 'apt.package' + hosting = ['*', 'local.machine'] + weight = 1 + reason = 'Primary use case due to the specialization of Ansible.' + details = + '"ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements' + + generate(name: string, type: NodeType) { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...ApplicationDirectory(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: AnsibleSoftwareApplicationAptPackageCreateTasks(), + }, + }, + }, + configure: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: AnsibleSoftwareApplicationConfigureTasks(), + }, + }, + }, + start: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: AnsibleSoftwareApplicationStartTasks(), + }, + }, + }, + stop: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: AnsibleSoftwareApplicationStopTasks(), + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + ...AnsibleSoftwareApplicationDeleteTasks(), + { + ...AnsibleSoftwareApplicationAptPackageDeleteTask(), + }, + ], + }, + }, + }, + }, + }, + }, + } + } +} + +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/index.ts new file mode 100644 index 0000000000..c76a810960 --- /dev/null +++ b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/index.ts @@ -0,0 +1,4 @@ +import ansible from './ansible' +import terraform from './terraform' + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/terraform/index.ts new file mode 100644 index 0000000000..791b63d904 --- /dev/null +++ b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/terraform/index.ts @@ -0,0 +1,114 @@ +import {NodeType} from '#spec/node-type' +import { + BashSoftwareApplicationAptPackageCreate, + BashSoftwareApplicationAptPackageDelete, + BashSoftwareApplicationConfigure, + BashSoftwareApplicationDelete, + BashSoftwareApplicationStart, + BashSoftwareApplicationStop, +} from '#technologies/plugins/rules/generators/software-application/utils' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import { + ApplicationDirectory, + MetadataGenerated, + OpenstackMachineCredentials, + OpenstackMachineHost, +} from '#technologies/plugins/rules/utils/utils' +import * as utils from '#utils' + +class Generator extends GeneratorAbstract { + component = 'software.application' + technology = 'terraform' + artifact = 'apt.package' + hosting = ['*', 'local.machine'] + weight = 0 + reason = 'Ansible is more specialized. Also using provisioners is a "last resort".' + details = '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts' + + generate(name: string, type: NodeType) { + return { + derived_from: name, + metadata: {...MetadataGenerated()}, + properties: { + ...OpenstackMachineCredentials(), + ...OpenstackMachineHost(), + ...ApplicationDirectory(), + }, + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + resource: { + local_file: { + tmp_create: { + content: BashSoftwareApplicationAptPackageCreate({ + name, + type, + artifact: this.artifact, + }), + filename: `/tmp/create-${name}.sh`, + }, + tmp_configure: { + content: BashSoftwareApplicationConfigure(), + filename: `/tmp/configure-${name}.sh`, + }, + tmp_start: { + content: BashSoftwareApplicationStart({assert: false}), + filename: `/tmp/start-${name}.sh`, + }, + tmp_stop: { + content: BashSoftwareApplicationStop({assert: false}), + filename: `/tmp/stop-${name}.sh`, + }, + tmp_delete: { + content: utils.concat([ + BashSoftwareApplicationDelete(), + BashSoftwareApplicationAptPackageDelete(), + ]), + filename: `/tmp/delete-${name}.sh`, + }, + }, + terraform_data: { + vm: [ + { + provisioner: { + depends_on: [ + 'local_file.tmp_artifact', + 'local_file.tmp_create', + 'local_file.tmp_configure', + 'local_file.tmp_start', + 'local_file.tmp_stop', + 'local_file.tmp_delete', + ], + 'local-exec': [ + { + inline: [ + `sudo bash /tmp/create-${name}.sh`, + `sudo bash /tmp/configure-${name}.sh`, + `sudo bash /tmp/start-${name}.sh`, + ], + }, + { + inline: [ + `sudo bash /tmp/stop-${name}.sh`, + `sudo bash /tmp/delete-${name}.sh`, + ], + when: 'destroy', + }, + ], + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + } +} + +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/ansible/index.ts index ab230b193e..a4ad339610 100644 --- a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/ansible/index.ts @@ -1,16 +1,14 @@ -import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' import {NodeType} from '#spec/node-type' import { - AnsibleSoftwareApplicationSourceArchiveConfigure, - AnsibleSoftwareApplicationSourceArchiveDelete, - AnsibleSoftwareApplicationSourceArchiveStart, - AnsibleSoftwareApplicationSourceArchiveStop, + AnsibleSoftwareApplicationAptPackageCreateTasks, + AnsibleSoftwareApplicationAptPackageDeleteTask, + AnsibleSoftwareApplicationConfigureTasks, + AnsibleSoftwareApplicationDeleteTasks, + AnsibleSoftwareApplicationStartTasks, + AnsibleSoftwareApplicationStopTasks, } from '#technologies/plugins/rules/generators/software-application/utils' import {GeneratorAbstract} from '#technologies/plugins/rules/types' import { - AnsibleCallManagementOperationTask, - AnsibleCopyManagementOperationTask, - AnsibleCreateApplicationDirectoryTask, AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, AnsibleWaitForSSHTask, @@ -56,66 +54,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - { - name: 'run setup script', - 'ansible.builtin.shell': - 'curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash -', - args: { - executable: '/bin/bash', - }, - when: '".artifacts::apt_package::script" | eval != ""', - }, - { - name: 'add apt key', - 'ansible.builtin.apt_key': { - url: '{{ ".artifacts::apt_package::key" | eval }}', - keyring: - '/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg', - state: 'present', - }, - when: '".artifacts::apt_package::key" | eval != ""', - }, - { - name: 'add apt repository', - 'ansible.builtin.apt_repository': { - repo: 'deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}', - filename: '{{ ".artifacts::apt_package::repository" | eval }}', - state: 'present', - }, - when: '".artifacts::apt_package::source" | eval != ""', - }, - { - name: 'update apt cache', - 'ansible.builtin.apt': { - update_cache: 'yes', - }, - }, - { - name: 'install dependencies', - 'ansible.builtin.apt': { - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}', - state: 'present', - }, - when: '".artifacts::apt_package::dependencies" | eval != ""', - }, - { - name: 'install package', - 'ansible.builtin.apt': { - name: '{{ ".artifacts::apt_package::file" | eval }}', - state: 'present', - }, - environment: - '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}', - }, - { - ...AnsibleCreateApplicationDirectoryTask(), - }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), - }, + ...AnsibleSoftwareApplicationAptPackageCreateTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -131,7 +70,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveConfigure(), + ...AnsibleSoftwareApplicationConfigureTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -147,7 +86,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveStart(), + ...AnsibleSoftwareApplicationStartTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -163,7 +102,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveStop(), + ...AnsibleSoftwareApplicationStopTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -179,13 +118,9 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveDelete(), + ...AnsibleSoftwareApplicationDeleteTasks(), { - name: 'uninstall package', - 'ansible.builtin.apt': { - name: '{{ ".artifacts::apt_package::file" | eval }}', - state: 'absent', - }, + ...AnsibleSoftwareApplicationAptPackageDeleteTask(), }, ], }, diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/terraform/index.ts index b4012c136b..dd69b51a55 100644 --- a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/remote-machine/terraform/index.ts @@ -4,7 +4,6 @@ import { BashSoftwareApplicationAptPackageDelete, BashSoftwareApplicationConfigure, BashSoftwareApplicationDelete, - BashSoftwareApplicationSourceArchiveCreate, BashSoftwareApplicationStart, BashSoftwareApplicationStop, } from '#technologies/plugins/rules/generators/software-application/utils' @@ -53,14 +52,11 @@ class Generator extends GeneratorAbstract { provisioner: { file: [ { - content: utils.concat([ - BashSoftwareApplicationSourceArchiveCreate({ - name, - type, - artifact: this.artifact, - }), - BashSoftwareApplicationAptPackageCreate(), - ]), + content: BashSoftwareApplicationAptPackageCreate({ + name, + type, + artifact: this.artifact, + }), destination: `/tmp/create-${name}.sh`, }, { diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts index bfccaf0078..3b797792af 100644 --- a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts @@ -1,10 +1,10 @@ import {NodeType} from '#spec/node-type' import { - AnsibleSoftwareApplicationSourceArchiveConfigure, + AnsibleSoftwareApplicationConfigureTasks, + AnsibleSoftwareApplicationDeleteTasks, AnsibleSoftwareApplicationSourceArchiveCreate, - AnsibleSoftwareApplicationSourceArchiveDelete, - AnsibleSoftwareApplicationSourceArchiveStart, - AnsibleSoftwareApplicationSourceArchiveStop, + AnsibleSoftwareApplicationStartTasks, + AnsibleSoftwareApplicationStopTasks, } from '#technologies/plugins/rules/generators/software-application/utils' import {GeneratorAbstract} from '#technologies/plugins/rules/types' import {AnsibleOrchestratorOperation, AnsibleWaitForSSHTask} from '#technologies/plugins/rules/utils/ansible' @@ -69,7 +69,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveConfigure(), + ...AnsibleSoftwareApplicationConfigureTasks(), ], }, }, @@ -84,7 +84,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveStart(), + ...AnsibleSoftwareApplicationStartTasks(), ], }, }, @@ -99,7 +99,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveStop(), + ...AnsibleSoftwareApplicationStopTasks(), ], }, }, @@ -114,7 +114,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveDelete(), + ...AnsibleSoftwareApplicationDeleteTasks(), ], }, }, diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts index 5d727e6432..fce8a22d25 100644 --- a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts @@ -24,7 +24,7 @@ class Generator extends GeneratorAbstract { hosting = ['*', 'local.machine'] weight = 0 reason = 'Ansible is more specialized. Also using provisioners is a "last resort".' - details = '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' + details = '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts' generate(name: string, type: NodeType) { return { diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/ansible/index.ts index 2b0718ebf9..309c4e7450 100644 --- a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/ansible/index.ts @@ -1,10 +1,10 @@ import {NodeType} from '#spec/node-type' import { - AnsibleSoftwareApplicationSourceArchiveConfigure, + AnsibleSoftwareApplicationConfigureTasks, + AnsibleSoftwareApplicationDeleteTasks, AnsibleSoftwareApplicationSourceArchiveCreate, - AnsibleSoftwareApplicationSourceArchiveDelete, - AnsibleSoftwareApplicationSourceArchiveStart, - AnsibleSoftwareApplicationSourceArchiveStop, + AnsibleSoftwareApplicationStartTasks, + AnsibleSoftwareApplicationStopTasks, } from '#technologies/plugins/rules/generators/software-application/utils' import {GeneratorAbstract} from '#technologies/plugins/rules/types' import { @@ -73,7 +73,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveConfigure(), + ...AnsibleSoftwareApplicationConfigureTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -89,7 +89,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveStart(), + ...AnsibleSoftwareApplicationStartTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -105,7 +105,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveStop(), + ...AnsibleSoftwareApplicationStopTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -121,7 +121,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveDelete(), + ...AnsibleSoftwareApplicationDeleteTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], diff --git a/src/technologies/plugins/rules/generators/software-application/utils.ts b/src/technologies/plugins/rules/generators/software-application/utils.ts index f141fe4cf1..58ecbc448d 100644 --- a/src/technologies/plugins/rules/generators/software-application/utils.ts +++ b/src/technologies/plugins/rules/generators/software-application/utils.ts @@ -51,7 +51,7 @@ export function AnsibleSoftwareApplicationSourceArchiveCreate(options: {artifact ] } -export function AnsibleSoftwareApplicationSourceArchiveConfigure() { +export function AnsibleSoftwareApplicationConfigureTasks() { return [ { ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), @@ -62,7 +62,7 @@ export function AnsibleSoftwareApplicationSourceArchiveConfigure() { ] } -export function AnsibleSoftwareApplicationSourceArchiveStart() { +export function AnsibleSoftwareApplicationStartTasks() { return [ { ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.START), @@ -76,7 +76,7 @@ export function AnsibleSoftwareApplicationSourceArchiveStart() { ] } -export function AnsibleSoftwareApplicationSourceArchiveStop() { +export function AnsibleSoftwareApplicationStopTasks() { return [ { ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.STOP), @@ -90,7 +90,7 @@ export function AnsibleSoftwareApplicationSourceArchiveStop() { ] } -export function AnsibleSoftwareApplicationSourceArchiveDelete() { +export function AnsibleSoftwareApplicationDeleteTasks() { return [ { ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), @@ -192,8 +192,83 @@ ${BashDeleteApplicationDirectory()} `) } -export function BashSoftwareApplicationAptPackageCreate() { +export function AnsibleSoftwareApplicationAptPackageCreateTasks() { + return [ + { + name: 'run setup script', + 'ansible.builtin.shell': 'curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash -', + args: { + executable: '/bin/bash', + }, + when: '".artifacts::apt_package::script" | eval != ""', + }, + { + name: 'add apt key', + 'ansible.builtin.apt_key': { + url: '{{ ".artifacts::apt_package::key" | eval }}', + keyring: '/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg', + state: 'present', + }, + when: '".artifacts::apt_package::key" | eval != ""', + }, + { + name: 'add apt repository', + 'ansible.builtin.apt_repository': { + repo: 'deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}', + filename: '{{ ".artifacts::apt_package::repository" | eval }}', + state: 'present', + }, + when: '".artifacts::apt_package::source" | eval != ""', + }, + { + name: 'update apt cache', + 'ansible.builtin.apt': { + update_cache: 'yes', + }, + }, + { + name: 'install dependencies', + 'ansible.builtin.apt': { + name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}', + state: 'present', + }, + when: '".artifacts::apt_package::dependencies" | eval != ""', + }, + { + name: 'install package', + 'ansible.builtin.apt': { + name: '{{ ".artifacts::apt_package::file" | eval }}', + state: 'present', + }, + environment: + '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}', + }, + { + ...AnsibleCreateApplicationDirectoryTask(), + }, + { + ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), + }, + { + ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), + }, + ] +} + +export function AnsibleSoftwareApplicationAptPackageDeleteTask() { + return { + name: 'uninstall package', + 'ansible.builtin.apt': { + name: '{{ ".artifacts::apt_package::file" | eval }}', + state: 'absent', + }, + } +} + +export function BashSoftwareApplicationAptPackageCreate(options: {name: string; type: NodeType; artifact: string}) { return utils.trim(` +${BASH_HEADER} + # Run setup script if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - @@ -219,6 +294,21 @@ fi # Install package {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y + +# Create application directory +${BashCreateApplicationDirectory()} + +# Create application environment +${BashCreateApplicationEnvironment(options.type)} + +# Create vintner directory +${BashCreateVintnerDirectory()} + +# Copy operation +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} + +# Execute operation +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CREATE)} `) } diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts index 046118315c..8ae0d9a1f2 100644 --- a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts @@ -1,10 +1,10 @@ import {NodeType} from '#spec/node-type' import { - AnsibleSoftwareApplicationSourceArchiveConfigure, + AnsibleSoftwareApplicationConfigureTasks, + AnsibleSoftwareApplicationDeleteTasks, AnsibleSoftwareApplicationSourceArchiveCreate, - AnsibleSoftwareApplicationSourceArchiveDelete, - AnsibleSoftwareApplicationSourceArchiveStart, - AnsibleSoftwareApplicationSourceArchiveStop, + AnsibleSoftwareApplicationStartTasks, + AnsibleSoftwareApplicationStopTasks, } from '#technologies/plugins/rules/generators/software-application/utils' import {GeneratorAbstract} from '#technologies/plugins/rules/types' import {AnsibleOrchestratorOperation, AnsibleWaitForSSHTask} from '#technologies/plugins/rules/utils/ansible' @@ -69,7 +69,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveConfigure(), + ...AnsibleSoftwareApplicationConfigureTasks(), ], }, }, @@ -84,7 +84,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveStart(), + ...AnsibleSoftwareApplicationStartTasks(), ], }, }, @@ -99,7 +99,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveStop(), + ...AnsibleSoftwareApplicationStopTasks(), ], }, }, @@ -114,7 +114,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveDelete(), + ...AnsibleSoftwareApplicationDeleteTasks(), ], }, }, diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts index edea24a178..4055b5c7a5 100644 --- a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts @@ -24,7 +24,7 @@ class Generator extends GeneratorAbstract { hosting = ['*', 'local.machine'] weight = 0 reason = 'Ansible is more specialized. Also using provisioners is a "last resort".' - details = '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' + details = '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts' generate(name: string, type: NodeType) { return { diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/ansible/index.ts index 3190ba73a4..4186b80e9b 100644 --- a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/ansible/index.ts @@ -1,10 +1,10 @@ import {NodeType} from '#spec/node-type' import { - AnsibleSoftwareApplicationSourceArchiveConfigure, + AnsibleSoftwareApplicationConfigureTasks, + AnsibleSoftwareApplicationDeleteTasks, AnsibleSoftwareApplicationSourceArchiveCreate, - AnsibleSoftwareApplicationSourceArchiveDelete, - AnsibleSoftwareApplicationSourceArchiveStart, - AnsibleSoftwareApplicationSourceArchiveStop, + AnsibleSoftwareApplicationStartTasks, + AnsibleSoftwareApplicationStopTasks, } from '#technologies/plugins/rules/generators/software-application/utils' import {GeneratorAbstract} from '#technologies/plugins/rules/types' import { @@ -80,7 +80,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveConfigure(), + ...AnsibleSoftwareApplicationConfigureTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -96,7 +96,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveStart(), + ...AnsibleSoftwareApplicationStartTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -112,7 +112,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveStop(), + ...AnsibleSoftwareApplicationStopTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -128,7 +128,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveDelete(), + ...AnsibleSoftwareApplicationDeleteTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], From b9299989151eaf255c8ba5b895e11ef6be2cb1a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Sun, 8 Sep 2024 15:21:11 +0200 Subject: [PATCH 11/18] continue --- .../plugins/rules/generators/ingress/index.ts | 6 +- .../rules/generators/ingress/machine/index.ts | 4 + .../machine/local-machine/ansible/index.ts | 69 +++++++++ .../local-machine}/index.ts | 0 .../machine/local-machine/terraform/index.ts | 64 ++++++++ .../remote-machine/ansible/index.ts | 41 +---- .../machine}/remote-machine/index.ts | 0 .../remote-machine/terraform/index.ts | 25 +--- .../rules/generators/ingress/machine/utils.ts | 65 ++++++++ .../mysql-database/mysql-dbms/index.ts | 6 +- .../mysql-dbms/machine/index.ts | 4 + .../machine/local-machine/ansible/index.ts | 112 ++++++++++++++ .../mysql-dbms/machine/local-machine/index.ts | 4 + .../machine/local-machine/terraform/index.ts | 85 +++++++++++ .../remote-machine/ansible/index.ts | 23 +-- .../machine/remote-machine/index.ts | 4 + .../remote-machine/terraform/index.ts | 24 +-- .../asterisk/remote-machine/ansible/index.ts | 140 +++++------------- .../asterisk/remote-machine/ansible/index.ts | 139 +++++------------ .../machine/local-machine/ansible/index.ts | 4 +- .../machine/remote-machine/ansible/index.ts | 4 +- .../generators/software-application/utils.ts | 2 +- .../machine/local-machine/ansible/index.ts | 4 +- .../machine/remote-machine/ansible/index.ts | 4 +- src/technologies/plugins/rules/types.ts | 4 +- .../plugins/rules/utils/ansible.ts | 53 +++++++ 26 files changed, 589 insertions(+), 301 deletions(-) create mode 100644 src/technologies/plugins/rules/generators/ingress/machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/ingress/machine/local-machine/ansible/index.ts rename src/technologies/plugins/rules/generators/ingress/{remote-machine => machine/local-machine}/index.ts (100%) create mode 100644 src/technologies/plugins/rules/generators/ingress/machine/local-machine/terraform/index.ts rename src/technologies/plugins/rules/generators/ingress/{ => machine}/remote-machine/ansible/index.ts (55%) rename src/technologies/plugins/rules/generators/{mysql-database/mysql-dbms => ingress/machine}/remote-machine/index.ts (100%) rename src/technologies/plugins/rules/generators/ingress/{ => machine}/remote-machine/terraform/index.ts (83%) create mode 100644 src/technologies/plugins/rules/generators/ingress/machine/utils.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/local-machine/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/local-machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/local-machine/terraform/index.ts rename src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/{ => machine}/remote-machine/ansible/index.ts (91%) create mode 100644 src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/remote-machine/index.ts rename src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/{ => machine}/remote-machine/terraform/index.ts (89%) diff --git a/src/technologies/plugins/rules/generators/ingress/index.ts b/src/technologies/plugins/rules/generators/ingress/index.ts index 2a0968b885..b1024ba430 100644 --- a/src/technologies/plugins/rules/generators/ingress/index.ts +++ b/src/technologies/plugins/rules/generators/ingress/index.ts @@ -1,6 +1,4 @@ import kubernetesCluster from './kubernetes-cluster' -import remoteMachine from './remote-machine' +import machine from './machine' -// TODO: local machine - -export default [kubernetesCluster, remoteMachine] +export default [kubernetesCluster, machine] diff --git a/src/technologies/plugins/rules/generators/ingress/machine/index.ts b/src/technologies/plugins/rules/generators/ingress/machine/index.ts new file mode 100644 index 0000000000..2e2d177edd --- /dev/null +++ b/src/technologies/plugins/rules/generators/ingress/machine/index.ts @@ -0,0 +1,4 @@ +import localMachine from './local-machine' +import remoteMachine from './remote-machine' + +export default [remoteMachine, localMachine] diff --git a/src/technologies/plugins/rules/generators/ingress/machine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/ingress/machine/local-machine/ansible/index.ts new file mode 100644 index 0000000000..5ee787c68d --- /dev/null +++ b/src/technologies/plugins/rules/generators/ingress/machine/local-machine/ansible/index.ts @@ -0,0 +1,69 @@ +import {AnsibleIngressCreateTasks} from '#technologies/plugins/rules/generators/ingress/machine/utils' +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' + +const generator: ImplementationGenerator = { + component: 'ingress', + technology: 'ansible', + hosting: ['local.machine'], + weight: 1, + reason: 'Primary use case due to the specialization of Ansible.', + details: + '"ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", "ansible.builtin.copy", and "ansible.builtin.systemd" tasks', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + attributes: { + // TODO: application address + application_address: { + type: 'string', + default: { + eval: '.::.requirements::[.name=host]::.target::application_address', + }, + }, + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: AnsibleIngressCreateTasks(), + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + name: 'uninstall package', + 'ansible.builtin.apt': { + name: 'caddy', + state: 'absent', + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/ingress/remote-machine/index.ts b/src/technologies/plugins/rules/generators/ingress/machine/local-machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/ingress/remote-machine/index.ts rename to src/technologies/plugins/rules/generators/ingress/machine/local-machine/index.ts diff --git a/src/technologies/plugins/rules/generators/ingress/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/ingress/machine/local-machine/terraform/index.ts new file mode 100644 index 0000000000..ec6f62e27e --- /dev/null +++ b/src/technologies/plugins/rules/generators/ingress/machine/local-machine/terraform/index.ts @@ -0,0 +1,64 @@ +import {BashIngressInstallationScript} from '#technologies/plugins/rules/generators/ingress/machine/utils' +import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import {MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' + +const generator: ImplementationGenerator = { + component: 'ingress', + technology: 'terraform', + hosting: ['local.machine'], + weight: 0, + reason: 'Ansible is more specialized. Also using provisioners is a "last resort".', + details: + '"local_file" resource to create the installation script and "terraform_data" to execute the script using the "local-exec" provisioner', + + generate: (name, type) => { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + attributes: { + // TODO: application address + application_address: { + type: 'string', + default: {eval: '.::.requirements::[.name=host]::.target::application_address'}, + }, + }, + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + resource: { + local_file: { + tmp_script: { + content: BashIngressInstallationScript, + destination: '/tmp/install-ingress.sh', + }, + }, + terraform_data: { + vm: [ + { + depends_on: ['local_file.tmp_script'], + provisioner: { + 'local-exec': [ + { + inline: ['sudo bash /tmp/install-ingress.sh'], + }, + ], + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + }, +} + +export default generator diff --git a/src/technologies/plugins/rules/generators/ingress/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/ingress/machine/remote-machine/ansible/index.ts similarity index 55% rename from src/technologies/plugins/rules/generators/ingress/remote-machine/ansible/index.ts rename to src/technologies/plugins/rules/generators/ingress/machine/remote-machine/ansible/index.ts index f8b01ba0ea..55fda09e9b 100644 --- a/src/technologies/plugins/rules/generators/ingress/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/ingress/machine/remote-machine/ansible/index.ts @@ -1,3 +1,4 @@ +import {AnsibleIngressCreateTasks} from '#technologies/plugins/rules/generators/ingress/machine/utils' import {ImplementationGenerator} from '#technologies/plugins/rules/types' import { AnsibleHostOperation, @@ -45,45 +46,7 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, - { - name: 'add apt key', - 'ansible.builtin.apt_key': { - url: 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key', - keyring: '/usr/share/keyrings/caddy-stable-archive-keyring.gpg', - state: 'present', - }, - }, - { - name: 'add apt repository', - 'ansible.builtin.apt_repository': { - repo: 'deb [signed-by=/usr/share/keyrings/caddy-stable-archive-keyring.gpg] https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main', - filename: 'caddy-stable', - state: 'present', - }, - }, - { - name: 'install package', - 'ansible.builtin.apt': { - name: 'caddy', - state: 'present', - update_cache: 'yes', - }, - }, - { - name: 'configure caddy', - 'ansible.builtin.copy': { - dest: '/etc/caddy/Caddyfile', - content: - ':80 {\n reverse_proxy localhost:{{ SELF.application_port }}\n}\n', - }, - }, - { - name: 'restart caddy', - 'ansible.builtin.systemd': { - name: 'caddy', - state: 'reloaded', - }, - }, + ...AnsibleIngressCreateTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/remote-machine/index.ts b/src/technologies/plugins/rules/generators/ingress/machine/remote-machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/remote-machine/index.ts rename to src/technologies/plugins/rules/generators/ingress/machine/remote-machine/index.ts diff --git a/src/technologies/plugins/rules/generators/ingress/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/ingress/machine/remote-machine/terraform/index.ts similarity index 83% rename from src/technologies/plugins/rules/generators/ingress/remote-machine/terraform/index.ts rename to src/technologies/plugins/rules/generators/ingress/machine/remote-machine/terraform/index.ts index 85b84f44ea..2fbad1c9e3 100644 --- a/src/technologies/plugins/rules/generators/ingress/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/ingress/machine/remote-machine/terraform/index.ts @@ -1,34 +1,13 @@ +import {BashIngressInstallationScript} from '#technologies/plugins/rules/generators/ingress/machine/utils' import {ImplementationGenerator} from '#technologies/plugins/rules/types' import {TerraformSSHConnection, TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { - BASH_HEADER, MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials, OpenstackMachineHost, } from '#technologies/plugins/rules/utils/utils' -const script = ` -${BASH_HEADER} - -# Install caddy -apt-get install -y debian-keyring debian-archive-keyring apt-transport-https curl -curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/gpg.key | gpg --dearmor --yes -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg -curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt | tee /etc/apt/sources.list.d/caddy-stable.list -apt-get update -apt-get install caddy -y - -# Configure caddy -cat < /etc/caddy/Caddyfile -:80 { - reverse_proxy localhost:{{ SELF.application_port }} -} -EOF - -# Restart caddy -systemctl reload caddy -` - const generator: ImplementationGenerator = { component: 'ingress', technology: 'terraform', @@ -71,7 +50,7 @@ const generator: ImplementationGenerator = { provisioner: { file: [ { - content: script, + content: BashIngressInstallationScript, destination: '/tmp/install-ingress.sh', }, ], diff --git a/src/technologies/plugins/rules/generators/ingress/machine/utils.ts b/src/technologies/plugins/rules/generators/ingress/machine/utils.ts new file mode 100644 index 0000000000..3b61d785c4 --- /dev/null +++ b/src/technologies/plugins/rules/generators/ingress/machine/utils.ts @@ -0,0 +1,65 @@ +import {BASH_HEADER} from '#technologies/plugins/rules/utils/utils' + +export const BashIngressInstallationScript = ` +${BASH_HEADER} + +# Install caddy +apt-get install -y debian-keyring debian-archive-keyring apt-transport-https curl +curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/gpg.key | gpg --dearmor --yes -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg +curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt | tee /etc/apt/sources.list.d/caddy-stable.list +apt-get update +apt-get install caddy -y + +# Configure caddy +cat < /etc/caddy/Caddyfile +:80 { + reverse_proxy localhost:{{ SELF.application_port }} +} +EOF + +# Restart caddy +systemctl reload caddy +` + +export function AnsibleIngressCreateTasks() { + return [ + { + name: 'add apt key', + 'ansible.builtin.apt_key': { + url: 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key', + keyring: '/usr/share/keyrings/caddy-stable-archive-keyring.gpg', + state: 'present', + }, + }, + { + name: 'add apt repository', + 'ansible.builtin.apt_repository': { + repo: 'deb [signed-by=/usr/share/keyrings/caddy-stable-archive-keyring.gpg] https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main', + filename: 'caddy-stable', + state: 'present', + }, + }, + { + name: 'install package', + 'ansible.builtin.apt': { + name: 'caddy', + state: 'present', + update_cache: 'yes', + }, + }, + { + name: 'configure caddy', + 'ansible.builtin.copy': { + dest: '/etc/caddy/Caddyfile', + content: ':80 {\n reverse_proxy localhost:{{ SELF.application_port }}\n}\n', + }, + }, + { + name: 'restart caddy', + 'ansible.builtin.systemd': { + name: 'caddy', + state: 'reloaded', + }, + }, + ] +} diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/index.ts index 5d42efbc7d..70586da6c5 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/index.ts @@ -1,8 +1,6 @@ import dockerEngine from './docker-engine' import gcpCloudSQL from './gcp-cloudsql' import kubernetesCluster from './kubernetes-cluster' -import remoteMachine from './remote-machine' +import machine from './machine' -// TODO: local machine - -export default [dockerEngine, gcpCloudSQL, kubernetesCluster, remoteMachine] +export default [dockerEngine, gcpCloudSQL, kubernetesCluster, machine] diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/index.ts new file mode 100644 index 0000000000..2e2d177edd --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/index.ts @@ -0,0 +1,4 @@ +import localMachine from './local-machine' +import remoteMachine from './remote-machine' + +export default [remoteMachine, localMachine] diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/local-machine/ansible/index.ts new file mode 100644 index 0000000000..be0ae5543e --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/local-machine/ansible/index.ts @@ -0,0 +1,112 @@ +import {NodeType} from '#spec/node-type' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' +import {MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' + +class Generator extends GeneratorAbstract { + component = 'mysql.database' + technology = 'ansible' + artifact = undefined + hosting = ['mysql.dbms', 'local.machine'] + weight = 1 + reason = 'Primary use case due to the specialization of Ansible.' + details = undefined + + generate(name: string, type: NodeType) { + 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: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + name: 'install pip', + 'ansible.builtin.apt': { + name: 'python3-pip', + state: 'present', + }, + }, + { + name: 'install pymysql', + 'ansible.builtin.pip': { + name: 'pymysql', + state: 'present', + }, + }, + { + name: 'create database', + 'community.mysql.mysql_db': { + name: '{{ SELF.database_name }}', + ...login, + }, + }, + { + name: 'create user (with privileges)', + 'community.mysql.mysql_user': { + ...user, + ...login, + }, + }, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + 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, + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + } +} + +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/local-machine/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/local-machine/index.ts new file mode 100644 index 0000000000..c76a810960 --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/local-machine/index.ts @@ -0,0 +1,4 @@ +import ansible from './ansible' +import terraform from './terraform' + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/local-machine/terraform/index.ts new file mode 100644 index 0000000000..b0644714a6 --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/local-machine/terraform/index.ts @@ -0,0 +1,85 @@ +import {NodeType} from '#spec/node-type' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import {MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' + +class Generator extends GeneratorAbstract { + component = 'mysql.database' + technology = 'terraform' + artifact = undefined + hosting = ['mysql.dbms', 'local.machine'] + weight = 1 + reason = 'Terraform provides a declarative module.' + details = undefined + + generate(name: string, type: NodeType) { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + terraform: [ + { + required_providers: [ + { + mysql: { + source: 'petoju/mysql', + version: '3.0.48', + }, + }, + ], + }, + ], + provider: { + mysql: [ + { + endpoint: '{{ HOST.application_address }}:{{ HOST.application_port }}', + password: '{{ HOST.dbms_password }}', + username: 'root', + }, + ], + }, + resource: { + mysql_database: { + database: [ + { + name: '{{ SELF.database_name }}', + }, + ], + }, + mysql_user: { + user: [ + { + host: '%', + plaintext_password: '{{ SELF.database_password }}', + user: '{{ SELF.database_user }}', + }, + ], + }, + mysql_grant: { + user: [ + { + database: '{{ SELF.database_name }}', + host: '%', + table: '*', + privileges: ['ALL'], + user: '${mysql_user.user.user}', + }, + ], + }, + }, + }, + }, + }, + }, + } + } +} + +export default new Generator() 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/machine/remote-machine/ansible/index.ts similarity index 91% rename from src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/remote-machine/ansible/index.ts rename to src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/remote-machine/ansible/index.ts index 68884260b1..29e47a5623 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/machine/remote-machine/ansible/index.ts @@ -1,4 +1,5 @@ -import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {NodeType} from '#spec/node-type' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' import { AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, @@ -6,14 +7,16 @@ import { } from '#technologies/plugins/rules/utils/ansible' import {MetadataGenerated, MetadataUnfurl, OpenstackMachineCredentials} from '#technologies/plugins/rules/utils/utils' -const generator: ImplementationGenerator = { - component: 'mysql.database', - technology: 'ansible', - hosting: ['mysql.dbms', 'remote.machine'], - weight: 1, - reason: 'Primary use case due to the specialization of Ansible.', +class Generator extends GeneratorAbstract { + component = 'mysql.database' + technology = 'ansible' + artifact = undefined + hosting = ['mysql.dbms', 'remote.machine'] + weight = 1 + reason = 'Primary use case due to the specialization of Ansible.' + details = undefined - generate: (name, type) => { + generate(name: string, type: NodeType) { const user = { name: '{{ SELF.database_user }}', password: '{{ SELF.database_password }}', @@ -118,7 +121,7 @@ const generator: ImplementationGenerator = { }, }, } - }, + } } -export default generator +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/remote-machine/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/remote-machine/index.ts new file mode 100644 index 0000000000..c76a810960 --- /dev/null +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/remote-machine/index.ts @@ -0,0 +1,4 @@ +import ansible from './ansible' +import terraform from './terraform' + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/remote-machine/terraform/index.ts similarity index 89% rename from src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/remote-machine/terraform/index.ts rename to src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/remote-machine/terraform/index.ts index 8d2bc22026..f83ea5b32e 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/remote-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/machine/remote-machine/terraform/index.ts @@ -1,4 +1,5 @@ -import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {NodeType} from '#spec/node-type' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' import { MetadataGenerated, @@ -7,14 +8,17 @@ import { OpenstackMachineHost, } from '#technologies/plugins/rules/utils/utils' -const generator: ImplementationGenerator = { - component: 'mysql.database', - technology: 'terraform', - hosting: ['mysql.dbms', 'remote.machine'], - weight: 0.5, - reason: 'Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized.', +class Generator extends GeneratorAbstract { + component = 'mysql.database' + technology = 'terraform' + artifact = undefined + hosting = ['mysql.dbms', 'remote.machine'] + weight = 0.5 + reason = + 'Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized.' + details = undefined - generate: (name, type) => { + generate(name: string, type: NodeType) { return { derived_from: name, metadata: { @@ -115,7 +119,7 @@ const generator: ImplementationGenerator = { }, }, } - }, + } } -export default generator +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/ansible/index.ts index aa21e97e91..3d10c8e444 100644 --- a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/ansible/index.ts @@ -1,18 +1,21 @@ -import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' -import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {NodeType} from '#spec/node-type' +import { + AnsibleSoftwareApplicationConfigureTasks, + AnsibleSoftwareApplicationDeleteTasks, + AnsibleSoftwareApplicationSourceArchiveCreateTasks, + AnsibleSoftwareApplicationStartTasks, + AnsibleSoftwareApplicationStopTasks, +} from '#technologies/plugins/rules/generators/software-application/utils' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' import { - AnsibleAssertOperationTask, - AnsibleCallManagementOperationTask, - AnsibleCopyManagementOperationTask, - AnsibleCreateApplicationDirectoryTask, - AnsibleCreateApplicationEnvironment, AnsibleCreateApplicationSystemdUnit, - AnsibleCreateVintnerDirectory, - AnsibleDeleteApplicationDirectoryTask, + AnsibleDeleteApplicationSystemdUnit, + AnsibleEnableApplicationSystemdUnit, AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, - AnsibleUnarchiveSourceArchiveFileTask, - AnsibleUnarchiveSourceArchiveUrlTask, + AnsibleStartApplicationSystemdUnit, + AnsibleStopApplicationSystemdUnit, + AnsibleSystemdDaemonReload, AnsibleWaitForSSHTask, } from '#technologies/plugins/rules/utils/ansible' import { @@ -22,19 +25,17 @@ import { OpenstackMachineCredentials, } from '#technologies/plugins/rules/utils/utils' -const artifact = 'tar.archive' - -const generator: ImplementationGenerator = { - component: 'service.application', - technology: 'ansible', - artifact, - hosting: ['*', 'remote.machine'], - weight: 1, - reason: 'Primary use case due to the specialization of Ansible. Special integration for systemd.', - details: - '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements', +class Generator extends GeneratorAbstract { + component = 'service.application' + technology = 'ansible' + artifact = 'tar.archive' + hosting = ['*', 'remote.machine'] + weight = 1 + reason = 'Primary use case due to the specialization of Ansible. Special integration for systemd.' + details = + '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements' - generate: (name, type) => { + generate(name: string, type: NodeType) { return { derived_from: name, metadata: { @@ -58,38 +59,15 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, - { - ...AnsibleCreateApplicationDirectoryTask(), - }, - { - ...AnsibleUnarchiveSourceArchiveFileTask(artifact), - }, - { - ...AnsibleUnarchiveSourceArchiveUrlTask(artifact), - }, - { - ...AnsibleCreateVintnerDirectory(), - }, - { - ...AnsibleCreateApplicationEnvironment(type), - }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), - }, + ...AnsibleSoftwareApplicationSourceArchiveCreateTasks({ + type, + artifact: this.artifact, + }), { ...AnsibleCreateApplicationSystemdUnit(), }, { - name: 'enable service', - 'ansible.builtin.systemd': { - name: '{{ SELF.application_name }}', - state: 'stopped', - enabled: 'yes', - daemon_reload: 'yes', - }, + ...AnsibleEnableApplicationSystemdUnit(), }, ], }, @@ -106,12 +84,7 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), - }, + ...AnsibleSoftwareApplicationConfigureTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -127,20 +100,9 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, + ...AnsibleSoftwareApplicationStartTasks(), { - ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.START), - }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.START), - }, - { - name: 'start service', - 'ansible.builtin.systemd': { - name: '{{ SELF.application_name }}', - state: 'started', - enabled: 'yes', - daemon_reload: 'yes', - }, + ...AnsibleStartApplicationSystemdUnit(), }, ], }, @@ -157,18 +119,9 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, + ...AnsibleSoftwareApplicationStopTasks(), { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), - }, - { - name: 'stop service', - 'ansible.builtin.systemd': { - name: '{{ SELF.application_name }}', - state: 'stopped', - }, + ...AnsibleStopApplicationSystemdUnit(), }, ], }, @@ -185,27 +138,12 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, + ...AnsibleSoftwareApplicationDeleteTasks(), { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), - }, - { - name: 'delete systemd service', - 'ansible.builtin.file': { - path: '/etc/systemd/system/{{ SELF.application_name }}.service', - state: 'absent', - }, - }, - { - name: 'reload daemon', - 'ansible.builtin.systemd': { - daemon_reload: true, - }, + ...AnsibleDeleteApplicationSystemdUnit(), }, { - ...AnsibleDeleteApplicationDirectoryTask(), + ...AnsibleSystemdDaemonReload(), }, ], }, @@ -216,7 +154,7 @@ const generator: ImplementationGenerator = { }, }, } - }, + } } -export default generator +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/ansible/index.ts index 05929f2381..11f2a3d973 100644 --- a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/ansible/index.ts @@ -1,17 +1,21 @@ -import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' -import {ImplementationGenerator} from '#technologies/plugins/rules/types' +import {NodeType} from '#spec/node-type' +import { + AnsibleSoftwareApplicationConfigureTasks, + AnsibleSoftwareApplicationDeleteTasks, + AnsibleSoftwareApplicationSourceArchiveCreateTasks, + AnsibleSoftwareApplicationStartTasks, + AnsibleSoftwareApplicationStopTasks, +} from '#technologies/plugins/rules/generators/software-application/utils' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' import { - AnsibleAssertOperationTask, - AnsibleCallManagementOperationTask, - AnsibleCopyManagementOperationTask, - AnsibleCreateApplicationDirectoryTask, - AnsibleCreateApplicationEnvironment, AnsibleCreateApplicationSystemdUnit, - AnsibleCreateVintnerDirectory, - AnsibleDeleteApplicationDirectoryTask, + AnsibleDeleteApplicationSystemdUnit, + AnsibleEnableApplicationSystemdUnit, AnsibleHostOperation, AnsibleHostOperationPlaybookArgs, - AnsibleUnarchiveSourceArchiveFileTask, + AnsibleStartApplicationSystemdUnit, + AnsibleStopApplicationSystemdUnit, + AnsibleSystemdDaemonReload, AnsibleWaitForSSHTask, } from '#technologies/plugins/rules/utils/ansible' import { @@ -21,19 +25,17 @@ import { OpenstackMachineCredentials, } from '#technologies/plugins/rules/utils/utils' -const artifact = 'zip.archive' - -const generator: ImplementationGenerator = { - component: 'service.application', - technology: 'ansible', - artifact, - hosting: ['*', 'remote.machine'], - weight: 1, - reason: 'Primary use case due to the specialization of Ansible. Special integration for systemd.', - details: - '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements', +class Generator extends GeneratorAbstract { + component = 'service.application' + technology = 'ansible' + artifact = 'zip.archive' + hosting = ['*', 'remote.machine'] + weight = 1 + reason = 'Primary use case due to the specialization of Ansible. Special integration for systemd.' + details = + '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements' - generate: (name, type) => { + generate(name: string, type: NodeType) { return { derived_from: name, metadata: { @@ -64,38 +66,15 @@ const generator: ImplementationGenerator = { update_cache: 'yes', }, }, - { - ...AnsibleCreateApplicationDirectoryTask(), - }, - { - ...AnsibleUnarchiveSourceArchiveFileTask(artifact), - }, - { - ...AnsibleUnarchiveSourceArchiveFileTask(artifact), - }, - { - ...AnsibleCreateVintnerDirectory(), - }, - { - ...AnsibleCreateApplicationEnvironment(type), - }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CREATE), - }, + ...AnsibleSoftwareApplicationSourceArchiveCreateTasks({ + type, + artifact: this.artifact, + }), { ...AnsibleCreateApplicationSystemdUnit(), }, { - name: 'enable service', - 'ansible.builtin.systemd': { - name: '{{ SELF.application_name }}', - state: 'stopped', - enabled: 'yes', - daemon_reload: 'yes', - }, + ...AnsibleEnableApplicationSystemdUnit(), }, ], }, @@ -112,12 +91,7 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.CONFIGURE), - }, + ...AnsibleSoftwareApplicationConfigureTasks(), ], }, playbookArgs: [...AnsibleHostOperationPlaybookArgs()], @@ -133,20 +107,9 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, + ...AnsibleSoftwareApplicationStartTasks(), { - ...AnsibleAssertOperationTask(MANAGEMENT_OPERATIONS.START), - }, - { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.START), - }, - { - name: 'start service', - 'ansible.builtin.systemd': { - name: '{{ SELF.application_name }}', - state: 'started', - enabled: 'yes', - daemon_reload: 'yes', - }, + ...AnsibleStartApplicationSystemdUnit(), }, ], }, @@ -163,18 +126,9 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, + ...AnsibleSoftwareApplicationStopTasks(), { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.STOP), - }, - { - name: 'stop service', - 'ansible.builtin.systemd': { - name: '{{ SELF.application_name }}', - state: 'stopped', - }, + ...AnsibleStopApplicationSystemdUnit(), }, ], }, @@ -191,27 +145,12 @@ const generator: ImplementationGenerator = { { ...AnsibleWaitForSSHTask(), }, + ...AnsibleSoftwareApplicationDeleteTasks(), { - ...AnsibleCopyManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), - }, - { - ...AnsibleCallManagementOperationTask(MANAGEMENT_OPERATIONS.DELETE), - }, - { - name: 'delete systemd service', - 'ansible.builtin.file': { - path: '/etc/systemd/system/{{ SELF.application_name }}.service', - state: 'absent', - }, - }, - { - name: 'reload daemon', - 'ansible.builtin.systemd': { - daemon_reload: true, - }, + ...AnsibleDeleteApplicationSystemdUnit(), }, { - ...AnsibleDeleteApplicationDirectoryTask(), + ...AnsibleSystemdDaemonReload(), }, ], }, @@ -222,7 +161,7 @@ const generator: ImplementationGenerator = { }, }, } - }, + } } -export default generator +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts index 3b797792af..c234bf2d85 100644 --- a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts @@ -2,7 +2,7 @@ import {NodeType} from '#spec/node-type' import { AnsibleSoftwareApplicationConfigureTasks, AnsibleSoftwareApplicationDeleteTasks, - AnsibleSoftwareApplicationSourceArchiveCreate, + AnsibleSoftwareApplicationSourceArchiveCreateTasks, AnsibleSoftwareApplicationStartTasks, AnsibleSoftwareApplicationStopTasks, } from '#technologies/plugins/rules/generators/software-application/utils' @@ -51,7 +51,7 @@ class Generator extends GeneratorAbstract { update_cache: 'yes', }, }, - ...AnsibleSoftwareApplicationSourceArchiveCreate({ + ...AnsibleSoftwareApplicationSourceArchiveCreateTasks({ type, artifact: this.artifact, }), diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/ansible/index.ts index 309c4e7450..b61413c66e 100644 --- a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/remote-machine/ansible/index.ts @@ -2,7 +2,7 @@ import {NodeType} from '#spec/node-type' import { AnsibleSoftwareApplicationConfigureTasks, AnsibleSoftwareApplicationDeleteTasks, - AnsibleSoftwareApplicationSourceArchiveCreate, + AnsibleSoftwareApplicationSourceArchiveCreateTasks, AnsibleSoftwareApplicationStartTasks, AnsibleSoftwareApplicationStopTasks, } from '#technologies/plugins/rules/generators/software-application/utils' @@ -54,7 +54,7 @@ class Generator extends GeneratorAbstract { { ...AnsibleWaitForSSHTask(), }, - ...AnsibleSoftwareApplicationSourceArchiveCreate({ + ...AnsibleSoftwareApplicationSourceArchiveCreateTasks({ type, artifact: this.artifact, }), diff --git a/src/technologies/plugins/rules/generators/software-application/utils.ts b/src/technologies/plugins/rules/generators/software-application/utils.ts index 58ecbc448d..77f93b5a47 100644 --- a/src/technologies/plugins/rules/generators/software-application/utils.ts +++ b/src/technologies/plugins/rules/generators/software-application/utils.ts @@ -25,7 +25,7 @@ import { } from '#technologies/plugins/rules/utils/utils' import * as utils from '#utils' -export function AnsibleSoftwareApplicationSourceArchiveCreate(options: {artifact: string; type: NodeType}) { +export function AnsibleSoftwareApplicationSourceArchiveCreateTasks(options: {artifact: string; type: NodeType}) { return [ { ...AnsibleCreateApplicationDirectoryTask(), diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts index 8ae0d9a1f2..ff0736e807 100644 --- a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts @@ -2,7 +2,7 @@ import {NodeType} from '#spec/node-type' import { AnsibleSoftwareApplicationConfigureTasks, AnsibleSoftwareApplicationDeleteTasks, - AnsibleSoftwareApplicationSourceArchiveCreate, + AnsibleSoftwareApplicationSourceArchiveCreateTasks, AnsibleSoftwareApplicationStartTasks, AnsibleSoftwareApplicationStopTasks, } from '#technologies/plugins/rules/generators/software-application/utils' @@ -51,7 +51,7 @@ class Generator extends GeneratorAbstract { update_cache: 'yes', }, }, - ...AnsibleSoftwareApplicationSourceArchiveCreate({ + ...AnsibleSoftwareApplicationSourceArchiveCreateTasks({ type, artifact: this.artifact, }), diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/ansible/index.ts index 4186b80e9b..6d4bfd1509 100644 --- a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/remote-machine/ansible/index.ts @@ -2,7 +2,7 @@ import {NodeType} from '#spec/node-type' import { AnsibleSoftwareApplicationConfigureTasks, AnsibleSoftwareApplicationDeleteTasks, - AnsibleSoftwareApplicationSourceArchiveCreate, + AnsibleSoftwareApplicationSourceArchiveCreateTasks, AnsibleSoftwareApplicationStartTasks, AnsibleSoftwareApplicationStopTasks, } from '#technologies/plugins/rules/generators/software-application/utils' @@ -61,7 +61,7 @@ class Generator extends GeneratorAbstract { update_cache: 'yes', }, }, - ...AnsibleSoftwareApplicationSourceArchiveCreate({ + ...AnsibleSoftwareApplicationSourceArchiveCreateTasks({ type, artifact: this.artifact, }), diff --git a/src/technologies/plugins/rules/types.ts b/src/technologies/plugins/rules/types.ts index 07a851aa26..400dbb54e3 100644 --- a/src/technologies/plugins/rules/types.ts +++ b/src/technologies/plugins/rules/types.ts @@ -47,7 +47,9 @@ export abstract class GeneratorAbstract implements ImplementationGenerator { abstract hosting: string[] abstract weight: number abstract reason: string - abstract details: string + + // TODO: make this mandatory + abstract details?: string abstract generate(name: string, type: NodeType): NodeType } diff --git a/src/technologies/plugins/rules/utils/ansible.ts b/src/technologies/plugins/rules/utils/ansible.ts index 0cf4013969..b0ea7e504d 100644 --- a/src/technologies/plugins/rules/utils/ansible.ts +++ b/src/technologies/plugins/rules/utils/ansible.ts @@ -162,6 +162,59 @@ export function AnsibleCreateApplicationSystemdUnit() { } } +export function AnsibleEnableApplicationSystemdUnit() { + return { + name: 'enable service', + 'ansible.builtin.systemd': { + name: '{{ SELF.application_name }}', + state: 'stopped', + enabled: 'yes', + daemon_reload: 'yes', + }, + } +} + +export function AnsibleStartApplicationSystemdUnit() { + return { + name: 'start service', + 'ansible.builtin.systemd': { + name: '{{ SELF.application_name }}', + state: 'started', + enabled: 'yes', + daemon_reload: 'yes', + }, + } +} + +export function AnsibleStopApplicationSystemdUnit() { + return { + name: 'stop service', + 'ansible.builtin.systemd': { + name: '{{ SELF.application_name }}', + state: 'stopped', + }, + } +} + +export function AnsibleDeleteApplicationSystemdUnit() { + return { + name: 'delete systemd service', + 'ansible.builtin.file': { + path: '/etc/systemd/system/{{ SELF.application_name }}.service', + state: 'absent', + }, + } +} + +export function AnsibleSystemdDaemonReload() { + return { + name: 'reload daemon', + 'ansible.builtin.systemd': { + daemon_reload: true, + }, + } +} + export function AnsibleCreateApplicationEnvironment(type: NodeType) { return { name: 'create .env file', From 6b0cbc7af4261483b05a6acf0151aa6eaadb503d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Sun, 8 Sep 2024 15:54:50 +0200 Subject: [PATCH 12/18] sort --- docs/docs/variability4tosca/rules/index.md | 560 ++++++++++++------ .../rules/technology-rules.yaml | 106 ++-- src/technologies/plugins/rules/registry.ts | 60 +- tasks/docs/generate/rules/template.ejs | 1 + 4 files changed, 477 insertions(+), 250 deletions(-) diff --git a/docs/docs/variability4tosca/rules/index.md b/docs/docs/variability4tosca/rules/index.md index 1e555c3f7d..5ab3014b9f 100644 --- a/docs/docs/variability4tosca/rules/index.md +++ b/docs/docs/variability4tosca/rules/index.md @@ -84,25 +84,23 @@ The node template is hosted on the node template "host 1" of node type [gcp.clou ### Scenario #2 In this scenario, the node template "component" of node type [bucket](/normative#bucket){target=_blank} is deployed. -The node template is hosted on the node template "host 1" of node type [minio.server](/normative#minioserver){target=_blank}, which is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 3" of node type [local.machine](/normative#localmachine){target=_blank}. - -
component(bucket)host 1(minio.server)...host 3(local.machine)hosthosthost
+This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [gcp.memorystore](/normative#gcpmemorystore){target=_blank}. +
component(bucket)artifact(cache.image)host 1(gcp.memorystore)host
-!!! success "Ansible (Quality: 1)" - Primary use case due to the specialization of Ansible. -!!! success "Terraform (Quality: 1)" - Terraform provides a declarative module. +!!! info "Ansible (Quality: 0.5)" + Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. ### Scenario #3 In this scenario, the node template "component" of node type [bucket](/normative#bucket){target=_blank} is deployed. -The node template is hosted on the node template "host 1" of node type [minio.server](/normative#minioserver){target=_blank}, which is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 3" of node type [remote.machine](/normative#remotemachine){target=_blank}. +The node template is hosted on the node template "host 1" of node type [minio.server](/normative#minioserver){target=_blank}, which is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 3" of node type [local.machine](/normative#localmachine){target=_blank}. -
component(bucket)host 1(minio.server)...host 3(remote.machine)hosthosthost
+
component(bucket)host 1(minio.server)...host 3(local.machine)hosthosthost
!!! success "Ansible (Quality: 1)" @@ -116,9 +114,9 @@ The node template is hosted on the node template "host 1" of node type [minio.se ### Scenario #4 In this scenario, the node template "component" of node type [bucket](/normative#bucket){target=_blank} is deployed. -The node template is hosted on the node template "host 1" of node type [minio.server](/normative#minioserver){target=_blank}, which is hosted on the node template "host 2" of node type [kubernetes.cluster](/normative#kubernetescluster){target=_blank}. +The node template is hosted on the node template "host 1" of node type [minio.server](/normative#minioserver){target=_blank}, which is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 3" of node type [remote.machine](/normative#remotemachine){target=_blank}. -
component(bucket)host 1(minio.server)host 2(kubernetes.cluster)hosthost
+
component(bucket)host 1(minio.server)...host 3(remote.machine)hosthosthost
!!! success "Ansible (Quality: 1)" @@ -132,14 +130,16 @@ The node template is hosted on the node template "host 1" of node type [minio.se ### Scenario #5 In this scenario, the node template "component" of node type [bucket](/normative#bucket){target=_blank} is deployed. -This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. -The node template is hosted on the node template "host 1" of node type [gcp.memorystore](/normative#gcpmemorystore){target=_blank}. +The node template is hosted on the node template "host 1" of node type [minio.server](/normative#minioserver){target=_blank}, which is hosted on the node template "host 2" of node type [kubernetes.cluster](/normative#kubernetescluster){target=_blank}. -
component(bucket)artifact(cache.image)host 1(gcp.memorystore)host
+
component(bucket)host 1(minio.server)host 2(kubernetes.cluster)hosthost
-!!! info "Ansible (Quality: 0.5)" - Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. @@ -227,6 +227,22 @@ The node template is hosted on the node template "host 1" of node type [kubernet ### Scenario #2 +In this scenario, the node template "component" of node type [ingress](/normative#ingress){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(ingress)host 1(local.machine)host
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! failure "Terraform (Quality: 0)" + Ansible is more specialized. Also using provisioners is a "last resort". + + + +### Scenario #3 + In this scenario, the node template "component" of node type [ingress](/normative#ingress){target=_blank} is deployed. The node template is hosted on the node template "host 1" of node type [remote.machine](/normative#remotemachine){target=_blank}. @@ -321,6 +337,22 @@ The node template is hosted on the node template "host 1" of node type [mysql.db ### Scenario #5 +In this scenario, the node template "component" of node type [mysql.database](/normative#mysqldatabase){target=_blank} is deployed. +The node template is hosted on the node template "host 1" of node type [mysql.dbms](/normative#mysqldbms){target=_blank}, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(mysql.database)host 1(mysql.dbms)host 2(local.machine)hosthost
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. + + + +### Scenario #6 + In this scenario, the node template "component" of node type [mysql.database](/normative#mysqldatabase){target=_blank} is deployed. The node template is hosted on the node template "host 1" of node type [mysql.dbms](/normative#mysqldbms){target=_blank}, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. @@ -458,20 +490,6 @@ The following scenarios deploy a node template of node type [redis.server](/norm ### Scenario #1 -In this scenario, the node template "component" of node type [redis.server](/normative#redisserver){target=_blank} is deployed. -This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. -The node template is hosted on the node template "host 1" of node type [gcp.memorystore](/normative#gcpmemorystore){target=_blank}. - -
component(redis.server)artifact(cache.image)host 1(gcp.memorystore)host
- - -!!! success "Terraform (Quality: 1)" - Terraform provides a declarative module. - - - -### Scenario #2 - In this scenario, the node template "component" of node type [redis.server](/normative#redisserver){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. The node template is hosted on the node template "host 1" of node type [docker.engine](/normative#dockerengine){target=_blank}, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. @@ -490,7 +508,7 @@ The node template is hosted on the node template "host 1" of node type [docker.e -### Scenario #3 +### Scenario #2 In this scenario, the node template "component" of node type [redis.server](/normative#redisserver){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. @@ -510,6 +528,20 @@ The node template is hosted on the node template "host 1" of node type [docker.e +### Scenario #3 + +In this scenario, the node template "component" of node type [redis.server](/normative#redisserver){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [cache.image](/normative#cacheimage){target=_blank}. +The node template is hosted on the node template "host 1" of node type [gcp.memorystore](/normative#gcpmemorystore){target=_blank}. + +
component(redis.server)artifact(cache.image)host 1(gcp.memorystore)host
+ + +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. + + + ### Scenario #4 In this scenario, the node template "component" of node type [redis.server](/normative#redisserver){target=_blank} is deployed. @@ -668,25 +700,28 @@ The following scenarios deploy a node template of node type [software.applicatio ### Scenario #1 In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. -This node template is implemented by its deployment artifact "artifact" of artifact type [apt.package](/normative#aptpackage){target=_blank}. +This node template is implemented by its deployment artifact "artifact" of artifact type [apt.archive](/normative#aptarchive){target=_blank}. The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. -
component(software.application)artifact(apt.package)...host 2(remote.machine)hosthost
+
component(software.application)artifact(apt.archive)...host 2(remote.machine)hosthost
-!!! success "Ansible (Quality: 1)" - Primary use case due to the specialization of Ansible. +!!! failure "Terraform (Quality: 0)" + Ansible is more specialized. Also using provisioners is a "last resort". ### Scenario #2 In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. -This node template is implemented by its deployment artifact "artifact" of artifact type [apt.archive](/normative#aptarchive){target=_blank}. -The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. +This node template is implemented by its deployment artifact "artifact" of artifact type [apt.package](/normative#aptpackage){target=_blank}. +The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(software.application)artifact(apt.package)...host 2(local.machine)hosthost
-
component(software.application)artifact(apt.archive)...host 2(remote.machine)hosthost
+!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. !!! failure "Terraform (Quality: 0)" Ansible is more specialized. Also using provisioners is a "last resort". @@ -697,30 +732,27 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [apt.package](/normative#aptpackage){target=_blank}. -The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. +The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. -
component(software.application)artifact(apt.package)...host 2(local.machine)hosthost
+
component(software.application)artifact(apt.package)...host 2(remote.machine)hosthost
!!! success "Ansible (Quality: 1)" Primary use case due to the specialization of Ansible. -!!! failure "Terraform (Quality: 0)" - Ansible is more specialized. Also using provisioners is a "last resort". - ### Scenario #4 In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [tar.archive](/normative#tararchive){target=_blank}. -The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. +The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. -
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
+
component(software.application)artifact(tar.archive)...host 2(local.machine)hosthost
!!! info "Ansible (Quality: 0.5)" - While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application". + While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. !!! failure "Terraform (Quality: 0)" Ansible is more specialized. Also using provisioners is a "last resort". @@ -731,13 +763,13 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [tar.archive](/normative#tararchive){target=_blank}. -The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. +The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. -
component(software.application)artifact(tar.archive)...host 2(local.machine)hosthost
+
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
!!! info "Ansible (Quality: 0.5)" - While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. + While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application". !!! failure "Terraform (Quality: 0)" Ansible is more specialized. Also using provisioners is a "last resort". @@ -748,9 +780,9 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [zip.archive](/normative#ziparchive){target=_blank}. -The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. +The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. -
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
+
component(software.application)artifact(zip.archive)...host 2(local.machine)hosthost
!!! info "Ansible (Quality: 0.5)" @@ -765,9 +797,9 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w In this scenario, the node template "component" of node type [software.application](/normative#softwareapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [zip.archive](/normative#ziparchive){target=_blank}. -The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. +The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. -
component(software.application)artifact(zip.archive)...host 2(local.machine)hosthost
+
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
!!! info "Ansible (Quality: 0.5)" @@ -810,6 +842,7 @@ This appendix contains the deployment technology rules. | --- | --- | | Identifier | bucket::ansible@gcp.cloudstorage | | Component | [bucket](/normative#bucket){target=_blank} | +| Technology | ansible | | Hosting | [gcp.cloudstorage](/normative#gcpcloudstorage){target=_blank} | | Quality | 0.5 | | Reason | Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. | @@ -821,6 +854,7 @@ This appendix contains the deployment technology rules. | --- | --- | | Identifier | bucket::terraform@gcp.cloudstorage | | Component | [bucket](/normative#bucket){target=_blank} | +| Technology | terraform | | Hosting | [gcp.cloudstorage](/normative#gcpcloudstorage){target=_blank} | | Quality | 1 | | Reason | Terraform provides a declarative module. | @@ -830,997 +864,1131 @@ This appendix contains the deployment technology rules. ### Rule #3 | Attribute | Value | | --- | --- | +| Identifier | bucket#cache.image::ansible@gcp.memorystore | +| Component | [bucket](/normative#bucket){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Technology | ansible | +| Hosting | [gcp.memorystore](/normative#gcpmemorystore){target=_blank} | +| Quality | 0.5 | +| Reason | Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. | +| Details | | +| Graph |
component(bucket)artifact(cache.image)host 1(gcp.memorystore)host
| + +### Rule #4 +| Attribute | Value | +| --- | --- | | Identifier | bucket::ansible@minio.server->*->local.machine | | Component | [bucket](/normative#bucket){target=_blank} | +| Technology | ansible | | Hosting | [minio.server](/normative#minioserver){target=_blank} -> * -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | | | Graph |
component(bucket)host 1(minio.server)...host 3(local.machine)hosthosthost
| -### Rule #4 +### Rule #5 | Attribute | Value | | --- | --- | | Identifier | bucket::terraform@minio.server->*->local.machine | | Component | [bucket](/normative#bucket){target=_blank} | +| Technology | terraform | | Hosting | [minio.server](/normative#minioserver){target=_blank} -> * -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 1 | | Reason | Terraform provides a declarative module. | | Details | | | Graph |
component(bucket)host 1(minio.server)...host 3(local.machine)hosthosthost
| -### Rule #5 +### Rule #6 | Attribute | Value | | --- | --- | | Identifier | bucket::ansible@minio.server->*->remote.machine | | Component | [bucket](/normative#bucket){target=_blank} | +| Technology | ansible | | Hosting | [minio.server](/normative#minioserver){target=_blank} -> * -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | | | Graph |
component(bucket)host 1(minio.server)...host 3(remote.machine)hosthosthost
| -### Rule #6 +### Rule #7 | Attribute | Value | | --- | --- | | Identifier | bucket::terraform@minio.server->*->remote.machine | | Component | [bucket](/normative#bucket){target=_blank} | +| Technology | terraform | | Hosting | [minio.server](/normative#minioserver){target=_blank} -> * -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 1 | | Reason | Terraform provides a declarative module. | | Details | | | Graph |
component(bucket)host 1(minio.server)...host 3(remote.machine)hosthosthost
| -### Rule #7 +### Rule #8 | Attribute | Value | | --- | --- | | Identifier | bucket::ansible@minio.server->kubernetes.cluster | | Component | [bucket](/normative#bucket){target=_blank} | +| Technology | ansible | | Hosting | [minio.server](/normative#minioserver){target=_blank} -> [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | | | Graph |
component(bucket)host 1(minio.server)host 2(kubernetes.cluster)hosthost
| -### Rule #8 +### Rule #9 | Attribute | Value | | --- | --- | | Identifier | bucket::terraform@minio.server->kubernetes.cluster | | Component | [bucket](/normative#bucket){target=_blank} | +| Technology | terraform | | Hosting | [minio.server](/normative#minioserver){target=_blank} -> [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 1 | | Reason | Terraform provides a declarative module. | | Details | | | Graph |
component(bucket)host 1(minio.server)host 2(kubernetes.cluster)hosthost
| -### Rule #9 +### Rule #10 | Attribute | Value | | --- | --- | | Identifier | docker.engine::ansible@local.machine | | Component | [docker.engine](/normative#dockerengine){target=_blank} | +| Technology | ansible | | Hosting | [local.machine](/normative#localmachine){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | "ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks | | Graph |
component(docker.engine)host 1(local.machine)host
| -### Rule #10 +### Rule #11 | Attribute | Value | | --- | --- | | Identifier | docker.engine::terraform@local.machine | | Component | [docker.engine](/normative#dockerengine){target=_blank} | +| Technology | terraform | | Hosting | [local.machine](/normative#localmachine){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. Also using provisioners is a "last resort". | | Details | "local-exec" provider | | Graph |
component(docker.engine)host 1(local.machine)host
| -### Rule #11 +### Rule #12 | Attribute | Value | | --- | --- | | Identifier | docker.engine::ansible@remote.machine | | Component | [docker.engine](/normative#dockerengine){target=_blank} | +| Technology | ansible | | Hosting | [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | "ansible.builtin.shell", "ansible.builtin.group", and "ansible.builtin.user" tasks | | Graph |
component(docker.engine)host 1(remote.machine)host
| -### Rule #12 +### Rule #13 | Attribute | Value | | --- | --- | | Identifier | docker.engine::terraform@remote.machine | | Component | [docker.engine](/normative#dockerengine){target=_blank} | +| Technology | terraform | | Hosting | [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. Also using provisioners is a "last resort". | | Details | "remote-exec" provider | | Graph |
component(docker.engine)host 1(remote.machine)host
| -### Rule #13 +### Rule #14 | Attribute | Value | | --- | --- | | Identifier | gcp.service::ansible | | Component | [gcp.service](/normative#gcpservice){target=_blank} | +| Technology | ansible | | Quality | 1 | | Reason | Ansible provides a declarative module | | Details | "google.cloud.gcp_serviceusage_service" task | | Graph |
component(gcp.service)
| -### Rule #14 +### Rule #15 | Attribute | Value | | --- | --- | | Identifier | gcp.service::terraform | | Component | [gcp.service](/normative#gcpservice){target=_blank} | +| Technology | terraform | | Quality | 1 | | Reason | Terraform provides a declarative module. | | Details | "google_project_service" resource | | Graph |
component(gcp.service)
| -### Rule #15 +### Rule #16 | Attribute | Value | | --- | --- | | Identifier | ingress::ansible@kubernetes.cluster | | Component | [ingress](/normative#ingress){target=_blank} | +| Technology | ansible | | Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 0.5 | | Reason | Kubernetes is more specialized. | | Details | "kubernetes.core.k8s" task | | Graph |
component(ingress)host 1(kubernetes.cluster)host
| -### Rule #16 +### Rule #17 | Attribute | Value | | --- | --- | | Identifier | ingress::kubernetes@kubernetes.cluster | | Component | [ingress](/normative#ingress){target=_blank} | +| Technology | kubernetes | | Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 1 | | Reason | Kubernetes is the underlying technology. | | Details | Kubernetes manifest generated and applied | | Graph |
component(ingress)host 1(kubernetes.cluster)host
| -### Rule #17 +### Rule #18 | Attribute | Value | | --- | --- | | Identifier | ingress::terraform@kubernetes.cluster | | Component | [ingress](/normative#ingress){target=_blank} | +| Technology | terraform | | Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 0.5 | | Reason | Kubernetes is more specialized. | | Details | "kubernetes_service_v1" resource | | Graph |
component(ingress)host 1(kubernetes.cluster)host
| -### Rule #18 +### Rule #19 +| Attribute | Value | +| --- | --- | +| Identifier | ingress::ansible@local.machine | +| Component | [ingress](/normative#ingress){target=_blank} | +| Technology | ansible | +| Hosting | [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", "ansible.builtin.copy", and "ansible.builtin.systemd" tasks | +| Graph |
component(ingress)host 1(local.machine)host
| + +### Rule #20 +| Attribute | Value | +| --- | --- | +| Identifier | ingress::terraform@local.machine | +| Component | [ingress](/normative#ingress){target=_blank} | +| Technology | terraform | +| Hosting | [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0 | +| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | +| Details | "local_file" resource to create the installation script and "terraform_data" to execute the script using the "local-exec" provisioner | +| Graph |
component(ingress)host 1(local.machine)host
| + +### Rule #21 | Attribute | Value | | --- | --- | | Identifier | ingress::ansible@remote.machine | | Component | [ingress](/normative#ingress){target=_blank} | +| Technology | ansible | | Hosting | [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", "ansible.builtin.copy", and "ansible.builtin.systemd" tasks | | Graph |
component(ingress)host 1(remote.machine)host
| -### Rule #19 +### Rule #22 | Attribute | Value | | --- | --- | | Identifier | ingress::terraform@remote.machine | | Component | [ingress](/normative#ingress){target=_blank} | +| Technology | terraform | | Hosting | [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. Also using provisioners is a "last resort". | | Details | "terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner | | Graph |
component(ingress)host 1(remote.machine)host
| -### Rule #20 +### Rule #23 | Attribute | Value | | --- | --- | | Identifier | mysql.database::ansible@mysql.dbms->docker.engine->local.machine | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | ansible | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(local.machine)hosthosthost
| -### Rule #21 +### Rule #24 | Attribute | Value | | --- | --- | | Identifier | mysql.database::compose@mysql.dbms->docker.engine->local.machine | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | compose | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0 | | Reason | One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. | | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(local.machine)hosthosthost
| -### Rule #22 +### Rule #25 | Attribute | Value | | --- | --- | | Identifier | mysql.database::terraform@mysql.dbms->docker.engine->local.machine | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | terraform | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0.5 | | Reason | Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. | | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(local.machine)hosthosthost
| -### Rule #23 +### Rule #26 | Attribute | Value | | --- | --- | | Identifier | mysql.database::ansible@mysql.dbms->docker.engine->remote.machine | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | ansible | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(remote.machine)hosthosthost
| -### Rule #24 +### Rule #27 | Attribute | Value | | --- | --- | | Identifier | mysql.database::compose@mysql.dbms->docker.engine->remote.machine | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | compose | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0 | | Reason | One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. | | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(remote.machine)hosthosthost
| -### Rule #25 +### Rule #28 | Attribute | Value | | --- | --- | | Identifier | mysql.database::terraform@mysql.dbms->docker.engine->remote.machine | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | terraform | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0.5 | | Reason | Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. | | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(remote.machine)hosthosthost
| -### Rule #26 +### Rule #29 | Attribute | Value | | --- | --- | | Identifier | mysql.database::ansible@mysql.dbms->gcp.cloudsql | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | ansible | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [gcp.cloudsql](/normative#gcpcloudsql){target=_blank} | | Quality | 0.5 | | Reason | Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. | | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(gcp.cloudsql)hosthost
| -### Rule #27 +### Rule #30 | Attribute | Value | | --- | --- | | Identifier | mysql.database::terraform@mysql.dbms->gcp.cloudsql | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | terraform | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [gcp.cloudsql](/normative#gcpcloudsql){target=_blank} | | Quality | 1 | | Reason | Terraform provides a declarative module. | | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(gcp.cloudsql)hosthost
| -### Rule #28 +### Rule #31 | Attribute | Value | | --- | --- | | Identifier | mysql.database::ansible@mysql.dbms->kubernetes.cluster | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | ansible | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(kubernetes.cluster)hosthost
| -### Rule #29 +### Rule #32 | Attribute | Value | | --- | --- | | Identifier | mysql.database::kubernetes@mysql.dbms->kubernetes.cluster | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | kubernetes | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 0 | | Reason | Kubernetes Job with imperative parts, while declarative other technologies provide declarative modules. | | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(kubernetes.cluster)hosthost
| -### Rule #30 +### Rule #33 | Attribute | Value | | --- | --- | | Identifier | mysql.database::terraform@mysql.dbms->kubernetes.cluster | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | terraform | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. | | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(kubernetes.cluster)hosthost
| -### Rule #31 +### Rule #34 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.database::ansible@mysql.dbms->local.machine | +| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | ansible | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | | +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(local.machine)hosthost
| + +### Rule #35 +| Attribute | Value | +| --- | --- | +| Identifier | mysql.database::terraform@mysql.dbms->local.machine | +| Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | terraform | +| Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Terraform provides a declarative module. | +| Details | | +| Graph |
component(mysql.database)host 1(mysql.dbms)host 2(local.machine)hosthost
| + +### Rule #36 | Attribute | Value | | --- | --- | | Identifier | mysql.database::ansible@mysql.dbms->remote.machine | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | ansible | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(remote.machine)hosthost
| -### Rule #32 +### Rule #37 | Attribute | Value | | --- | --- | | Identifier | mysql.database::terraform@mysql.dbms->remote.machine | | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | +| Technology | terraform | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0.5 | | Reason | Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. | | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(remote.machine)hosthost
| -### Rule #33 +### Rule #38 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::ansible@docker.engine->local.machine | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | ansible | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0.5 | | Reason | Docker Compose is more specialized | | Details | "community.docker.docker_container" task | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #34 +### Rule #39 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::compose@docker.engine->local.machine | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | compose | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 1 | | Reason | Docker is the underlying technology. | | Details | docker-compose manifest generated and applied | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #35 +### Rule #40 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::terraform@docker.engine->local.machine | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | terraform | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0.5 | | Reason | Docker Compose is more specialized. | | Details | "docker_container" and "docker_image" resources | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #36 +### Rule #41 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::ansible@docker.engine->remote.machine | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | ansible | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0.5 | | Reason | Docker Compose is more specialized | | Details | "community.docker.docker_container" task | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #37 +### Rule #42 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::compose@docker.engine->remote.machine | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | compose | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 1 | | Reason | Docker is the underlying technology. | | Details | docker-compose manifest generated and applied | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #38 +### Rule #43 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::terraform@docker.engine->remote.machine | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | terraform | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0.5 | | Reason | Docker Compose is more specialized. | | Details | "docker_container" and "docker_image" resources | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #39 +### Rule #44 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::ansible@gcp.cloudsql | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | ansible | | Hosting | [gcp.cloudsql](/normative#gcpcloudsql){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | "google.cloud.gcp_sql_instance" and "google.cloud.gcp_sql_user" tasks | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(gcp.cloudsql)host
| -### Rule #40 +### Rule #45 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::terraform@gcp.cloudsql | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | terraform | | Hosting | [gcp.cloudsql](/normative#gcpcloudsql){target=_blank} | | Quality | 1 | | Reason | Terraform provides a declarative module. | | Details | "google_sql_database_instance" and "google_sql_user" resources | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(gcp.cloudsql)host
| -### Rule #41 +### Rule #46 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::ansible@kubernetes.cluster | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | ansible | | Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 0.5 | | Reason | Kubernetes is more specialized. | | Details | "kubernetes.core.k8s" tasks | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(kubernetes.cluster)host
| -### Rule #42 +### Rule #47 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::kubernetes@kubernetes.cluster | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | kubernetes | | Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 1 | | Reason | Kubernetes is the underlying technology. | | Details | Kubernetes manifest generated and applied | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(kubernetes.cluster)host
| -### Rule #43 +### Rule #48 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::terraform@kubernetes.cluster | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | terraform | | Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 0.5 | | Reason | Kubernetes is more specialized. | | Details | "kubernetes_deployment_v1" and "kubernetes_service_v1" resources | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(kubernetes.cluster)host
| -### Rule #44 +### Rule #49 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::ansible@local.machine | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | ansible | | Hosting | [local.machine](/normative#localmachine){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | "ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(local.machine)host
| -### Rule #45 +### Rule #50 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::terraform@local.machine | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | terraform | | Hosting | [local.machine](/normative#localmachine){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. Also using provisioners is a "last resort". | | Details | "terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(local.machine)host
| -### Rule #46 +### Rule #51 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::ansible@remote.machine | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | ansible | | Hosting | [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | "ansible.builtin.apt", "ansible.builtin.systemd", "ansible.builtin.copy", "ansible.builtin.lineinfile", and "community.mysql.mysql_user" tasks | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(remote.machine)host
| -### Rule #47 +### Rule #52 | Attribute | Value | | --- | --- | | Identifier | mysql.dbms#dbms.image::terraform@remote.machine | | Component | [mysql.dbms](/normative#mysqldbms){target=_blank} | | Artifact | [dbms.image](/normative#dbmsimage){target=_blank} | +| Technology | terraform | | Hosting | [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. Also using provisioners is a "last resort". | | Details | "terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(remote.machine)host
| -### Rule #48 -| Attribute | Value | -| --- | --- | -| Identifier | bucket#cache.image::ansible@gcp.memorystore | -| Component | [bucket](/normative#bucket){target=_blank} | -| Artifact | [cache.image](/normative#cacheimage){target=_blank} | -| Hosting | [gcp.memorystore](/normative#gcpmemorystore){target=_blank} | -| Quality | 0.5 | -| Reason | Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. | -| Details | | -| Graph |
component(bucket)artifact(cache.image)host 1(gcp.memorystore)host
| - -### Rule #49 -| Attribute | Value | -| --- | --- | -| Identifier | redis.server#cache.image::terraform@gcp.memorystore | -| Component | [redis.server](/normative#redisserver){target=_blank} | -| Artifact | [cache.image](/normative#cacheimage){target=_blank} | -| Hosting | [gcp.memorystore](/normative#gcpmemorystore){target=_blank} | -| Quality | 1 | -| Reason | Terraform provides a declarative module. | -| Details | | -| Graph |
component(redis.server)artifact(cache.image)host 1(gcp.memorystore)host
| - -### Rule #50 +### Rule #53 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::ansible@docker.engine->local.machine | | Component | [redis.server](/normative#redisserver){target=_blank} | | Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Technology | ansible | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0.5 | | Reason | Docker Compose is more specialized. | | Details | "community.docker.docker_container" task | | Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #51 +### Rule #54 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::compose@docker.engine->local.machine | | Component | [redis.server](/normative#redisserver){target=_blank} | | Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Technology | compose | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 1 | | Reason | Docker is the underlying technology. | | Details | docker compose manifest generated and applied | | Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #52 +### Rule #55 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::terraform@docker.engine->local.machine | | Component | [redis.server](/normative#redisserver){target=_blank} | | Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Technology | terraform | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0.5 | | Reason | Docker Compose is more specialized. | | Details | "docker_container" and "docker_image" resources | | Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #53 +### Rule #56 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::ansible@docker.engine->remote.machine | | Component | [redis.server](/normative#redisserver){target=_blank} | | Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Technology | ansible | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0.5 | | Reason | Docker Compose is more specialized. | | Details | "community.docker.docker_container" task | | Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #54 +### Rule #57 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::compose@docker.engine->remote.machine | | Component | [redis.server](/normative#redisserver){target=_blank} | | Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Technology | compose | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 1 | | Reason | Docker is the underlying technology. | | Details | docker compose manifest generated and applied | | Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #55 +### Rule #58 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::terraform@docker.engine->remote.machine | | Component | [redis.server](/normative#redisserver){target=_blank} | | Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Technology | terraform | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0.5 | | Reason | Docker Compose is more specialized. | | Details | "docker_container" and "docker_image" resources | | Graph |
component(redis.server)artifact(cache.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #56 +### Rule #59 +| Attribute | Value | +| --- | --- | +| Identifier | redis.server#cache.image::terraform@gcp.memorystore | +| Component | [redis.server](/normative#redisserver){target=_blank} | +| Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Technology | terraform | +| Hosting | [gcp.memorystore](/normative#gcpmemorystore){target=_blank} | +| Quality | 1 | +| Reason | Terraform provides a declarative module. | +| Details | | +| Graph |
component(redis.server)artifact(cache.image)host 1(gcp.memorystore)host
| + +### Rule #60 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::ansible@kubernetes.cluster | | Component | [redis.server](/normative#redisserver){target=_blank} | | Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Technology | ansible | | Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | | | Graph |
component(redis.server)artifact(cache.image)host 1(kubernetes.cluster)host
| -### Rule #57 +### Rule #61 | Attribute | Value | | --- | --- | | Identifier | redis.server#cache.image::terraform@kubernetes.cluster | | Component | [redis.server](/normative#redisserver){target=_blank} | | Artifact | [cache.image](/normative#cacheimage){target=_blank} | +| Technology | terraform | | Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 1 | | Reason | Terraform provides a declarative module. | | Details | | | Graph |
component(redis.server)artifact(cache.image)host 1(kubernetes.cluster)host
| -### Rule #58 +### Rule #62 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::ansible@docker.engine->local.machine | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Technology | ansible | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0.5 | | Reason | Docker Compose is more specialized. | | Details | "community.docker.docker_container" task | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #59 +### Rule #63 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::compose@docker.engine->local.machine | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Technology | compose | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 1 | | Reason | Docker is the underlying technology. | | Details | docker compose manifest generated and applied | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #60 +### Rule #64 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::terraform@docker.engine->local.machine | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Technology | terraform | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0.5 | | Reason | Docker Compose is more specialized. | | Details | "docker_container" and "docker_image" resources | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(local.machine)hosthost
| -### Rule #61 +### Rule #65 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::ansible@docker.engine->remote.machine | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Technology | ansible | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0.5 | | Reason | Docker Compose is more specialized. | | Details | "community.docker.docker_container" task | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #62 +### Rule #66 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::compose@docker.engine->remote.machine | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Technology | compose | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 1 | | Reason | Docker is the underlying technology. | | Details | docker compose manifest generated and applied | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #63 +### Rule #67 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::terraform@docker.engine->remote.machine | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Technology | terraform | | Hosting | [docker.engine](/normative#dockerengine){target=_blank} -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0.5 | | Reason | Docker Compose is more specialized. | | Details | "docker_container" and "docker_image" resources | | Graph |
component(service.application)artifact(docker.image)host 1(docker.engine)host 2(remote.machine)hosthost
| -### Rule #64 +### Rule #68 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::ansible@gcp.cloudrun | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Technology | ansible | | Hosting | [gcp.cloudrun](/normative#gcpcloudrun){target=_blank} | | Quality | 0 | | Reason | Custom module with imperative parts, while Terraform provides a declarative module. | | Details | "ansible.builtin.shell", "ansible.builtin.tempfile", and "ansible.builtin.copy" tasks | | Graph |
component(service.application)artifact(docker.image)host 1(gcp.cloudrun)host
| -### Rule #65 +### Rule #69 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::terraform@gcp.cloudrun | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Technology | terraform | | Hosting | [gcp.cloudrun](/normative#gcpcloudrun){target=_blank} | | Quality | 1 | | Reason | Terraform provides a declarative module. | | Details | "google_cloud_run_v2_service" and "google_cloud_run_service_iam_binding" resources | | Graph |
component(service.application)artifact(docker.image)host 1(gcp.cloudrun)host
| -### Rule #66 +### Rule #70 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::ansible@kubernetes.cluster | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Technology | ansible | | Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 0.5 | | Reason | Kubernetes is more specialized. | | Details | "kubernetes.core.k8s" tasks | | Graph |
component(service.application)artifact(docker.image)host 1(kubernetes.cluster)host
| -### Rule #67 +### Rule #71 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::kubernetes@kubernetes.cluster | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Technology | kubernetes | | Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 1 | | Reason | Kubernetes is the underlying technology. | | Details | Kubernetes manifest generated and applied | | Graph |
component(service.application)artifact(docker.image)host 1(kubernetes.cluster)host
| -### Rule #68 +### Rule #72 | Attribute | Value | | --- | --- | | Identifier | service.application#docker.image::terraform@kubernetes.cluster | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [docker.image](/normative#dockerimage){target=_blank} | +| Technology | terraform | | Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | | Quality | 0.5 | | Reason | Kubernetes is more specialized. | | Details | "kubernetes_deployment_v1" and "kubernetes_service_v1" resources | | Graph |
component(service.application)artifact(docker.image)host 1(kubernetes.cluster)host
| -### Rule #69 +### Rule #73 | Attribute | Value | | --- | --- | | Identifier | service.application#tar.archive::ansible@*->remote.machine | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [tar.archive](/normative#tararchive){target=_blank} | +| Technology | ansible | | Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. Special integration for systemd. | | Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements | | Graph |
component(service.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #70 +### Rule #74 | Attribute | Value | | --- | --- | | Identifier | service.application#tar.archive::terraform@*->remote.machine | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [tar.archive](/normative#tararchive){target=_blank} | +| Technology | terraform | | Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. Also using provisioners is a "last resort". | | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(service.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #71 +### Rule #75 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::ansible@*->remote.machine | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Technology | ansible | | Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. Special integration for systemd. | | Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements | | Graph |
component(service.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #72 +### Rule #76 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::terraform@*->remote.machine | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Technology | terraform | | Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. Also using provisioners is a "last resort". | | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(service.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #73 +### Rule #77 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::ansible@gcp.appengine | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Technology | ansible | | Hosting | [gcp.appengine](/normative#gcpappengine){target=_blank} | | Quality | 0 | | Reason | Custom module with imperative parts, while Terraform provides a declarative module. | | Details | "ansible.builtin.shell", "ansible.builtin.tempfile", "ansible.builtin.unarchive", and "ansible.builtin.copy" tasks | | Graph |
component(service.application)artifact(zip.archive)host 1(gcp.appengine)host
| -### Rule #74 +### Rule #78 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::terraform@gcp.appengine | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Technology | terraform | | Hosting | [gcp.appengine](/normative#gcpappengine){target=_blank} | | Quality | 1 | | Reason | Terraform provides a declarative module. | | Details | "google_app_engine_standard_app_version", "google_project_iam_member", "google_service_account", "google_storage_bucket", and "google_storage_bucket_object" resources | | Graph |
component(service.application)artifact(zip.archive)host 1(gcp.appengine)host
| -### Rule #75 -| Attribute | Value | -| --- | --- | -| Identifier | software.application#apt.package::ansible@*->remote.machine | -| Component | [software.application](/normative#softwareapplication){target=_blank} | -| Artifact | [apt.package](/normative#aptpackage){target=_blank} | -| Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 1 | -| Reason | Primary use case due to the specialization of Ansible. | -| Details | "ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements | -| Graph |
component(software.application)artifact(apt.package)...host 2(remote.machine)hosthost
| - -### Rule #76 +### Rule #79 | Attribute | Value | | --- | --- | | Identifier | software.application#apt.archive::terraform@*->remote.machine | | Component | [software.application](/normative#softwareapplication){target=_blank} | | Artifact | [apt.archive](/normative#aptarchive){target=_blank} | +| Technology | terraform | | Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. Also using provisioners is a "last resort". | | Details | "file" provisioner to upload scripts and "remote-exec" to execute scripts | | Graph |
component(software.application)artifact(apt.archive)...host 2(remote.machine)hosthost
| -### Rule #77 +### Rule #80 | Attribute | Value | | --- | --- | | Identifier | software.application#apt.package::ansible@*->local.machine | | Component | [software.application](/normative#softwareapplication){target=_blank} | | Artifact | [apt.package](/normative#aptpackage){target=_blank} | +| Technology | ansible | | Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 1 | | Reason | Primary use case due to the specialization of Ansible. | | Details | "ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements | | Graph |
component(software.application)artifact(apt.package)...host 2(local.machine)hosthost
| -### Rule #78 +### Rule #81 | Attribute | Value | | --- | --- | | Identifier | software.application#apt.package::terraform@*->local.machine | | Component | [software.application](/normative#softwareapplication){target=_blank} | | Artifact | [apt.package](/normative#aptpackage){target=_blank} | +| Technology | terraform | | Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. Also using provisioners is a "last resort". | | Details | "local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts | | Graph |
component(software.application)artifact(apt.package)...host 2(local.machine)hosthost
| -### Rule #79 -| Attribute | Value | -| --- | --- | -| Identifier | software.application#tar.archive::ansible@*->remote.machine | -| Component | [software.application](/normative#softwareapplication){target=_blank} | -| Artifact | [tar.archive](/normative#tararchive){target=_blank} | -| Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 0.5 | -| Reason | While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application". | -| Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | -| Graph |
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| - -### Rule #80 +### Rule #82 | Attribute | Value | | --- | --- | -| Identifier | software.application#tar.archive::terraform@*->remote.machine | +| Identifier | software.application#apt.package::ansible@*->remote.machine | | Component | [software.application](/normative#softwareapplication){target=_blank} | -| Artifact | [tar.archive](/normative#tararchive){target=_blank} | +| Artifact | [apt.package](/normative#aptpackage){target=_blank} | +| Technology | ansible | | Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | -| Quality | 0 | -| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | -| Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | -| Graph |
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | +| Details | "ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements | +| Graph |
component(software.application)artifact(apt.package)...host 2(remote.machine)hosthost
| -### Rule #81 +### Rule #83 | Attribute | Value | | --- | --- | | Identifier | software.application#tar.archive::ansible@*->local.machine | | Component | [software.application](/normative#softwareapplication){target=_blank} | | Artifact | [tar.archive](/normative#tararchive){target=_blank} | +| Technology | ansible | | Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0.5 | | Reason | While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. | | Details | "ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | | Graph |
component(software.application)artifact(tar.archive)...host 2(local.machine)hosthost
| -### Rule #82 +### Rule #84 | Attribute | Value | | --- | --- | | Identifier | software.application#tar.archive::terraform@*->local.machine | | Component | [software.application](/normative#softwareapplication){target=_blank} | | Artifact | [tar.archive](/normative#tararchive){target=_blank} | +| Technology | terraform | | Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. Also using provisioners is a "last resort". | | Details | "local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts | | Graph |
component(software.application)artifact(tar.archive)...host 2(local.machine)hosthost
| -### Rule #83 +### Rule #85 | Attribute | Value | | --- | --- | -| Identifier | software.application#zip.archive::ansible@*->remote.machine | +| Identifier | software.application#tar.archive::ansible@*->remote.machine | | Component | [software.application](/normative#softwareapplication){target=_blank} | -| Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Artifact | [tar.archive](/normative#tararchive){target=_blank} | +| Technology | ansible | | Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0.5 | -| Reason | While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. | -| Details | "ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | -| Graph |
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| +| Reason | While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application". | +| Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | +| Graph |
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #84 +### Rule #86 | Attribute | Value | | --- | --- | -| Identifier | software.application#zip.archive::terraform@*->remote.machine | +| Identifier | software.application#tar.archive::terraform@*->remote.machine | | Component | [software.application](/normative#softwareapplication){target=_blank} | -| Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Artifact | [tar.archive](/normative#tararchive){target=_blank} | +| Technology | terraform | | Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. Also using provisioners is a "last resort". | | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | -| Graph |
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| +| Graph |
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #85 +### Rule #87 | Attribute | Value | | --- | --- | | Identifier | software.application#zip.archive::ansible@*->local.machine | | Component | [software.application](/normative#softwareapplication){target=_blank} | | Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Technology | ansible | | Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0.5 | | Reason | While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. | | Details | "ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | | Graph |
component(software.application)artifact(zip.archive)...host 2(local.machine)hosthost
| -### Rule #86 +### Rule #88 | Attribute | Value | | --- | --- | | Identifier | software.application#zip.archive::terraform@*->local.machine | | Component | [software.application](/normative#softwareapplication){target=_blank} | | Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Technology | terraform | | Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. Also using provisioners is a "last resort". | | Details | "local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts | | Graph |
component(software.application)artifact(zip.archive)...host 2(local.machine)hosthost
| -### Rule #87 +### Rule #89 +| Attribute | Value | +| --- | --- | +| Identifier | software.application#zip.archive::ansible@*->remote.machine | +| Component | [software.application](/normative#softwareapplication){target=_blank} | +| Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Technology | ansible | +| Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 0.5 | +| Reason | While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. | +| Details | "ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | +| Graph |
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| + +### Rule #90 +| Attribute | Value | +| --- | --- | +| Identifier | software.application#zip.archive::terraform@*->remote.machine | +| Component | [software.application](/normative#softwareapplication){target=_blank} | +| Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Technology | terraform | +| Hosting | * -> [remote.machine](/normative#remotemachine){target=_blank} | +| Quality | 0 | +| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | +| Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | +| Graph |
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| + +### Rule #91 | Attribute | Value | | --- | --- | | Identifier | virtual.machine#machine.image::ansible@openstack.provider | | Component | [virtual.machine](/normative#virtualmachine){target=_blank} | | Artifact | [machine.image](/normative#machineimage){target=_blank} | +| Technology | ansible | | Hosting | [openstack.provider](/normative#openstackprovider){target=_blank} | | Quality | 0.5 | | Reason | Terraform is more specialized. | | Details | "openstack.cloud.security_group", "openstack.cloud.security_group_rule" and "openstack.cloud.server" tasks | | Graph |
component(virtual.machine)artifact(machine.image)host 1(openstack.provider)host
| -### Rule #88 +### Rule #92 | Attribute | Value | | --- | --- | | Identifier | virtual.machine#machine.image::terraform@openstack.provider | | Component | [virtual.machine](/normative#virtualmachine){target=_blank} | | Artifact | [machine.image](/normative#machineimage){target=_blank} | +| Technology | terraform | | Hosting | [openstack.provider](/normative#openstackprovider){target=_blank} | | Quality | 1 | | Reason | Terraform provides a declarative module. | diff --git a/docs/docs/variability4tosca/rules/technology-rules.yaml b/docs/docs/variability4tosca/rules/technology-rules.yaml index 0b864074d1..c70c424dcc 100644 --- a/docs/docs/variability4tosca/rules/technology-rules.yaml +++ b/docs/docs/variability4tosca/rules/technology-rules.yaml @@ -10,6 +10,13 @@ - gcp.cloudstorage weight: 1 reason: Terraform provides a declarative module. +- technology: ansible + component: bucket + artifact: cache.image + hosting: + - gcp.memorystore + weight: 0.5 + reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. - technology: ansible component: bucket hosting: @@ -117,6 +124,20 @@ weight: 0.5 reason: Kubernetes is more specialized. details: '"kubernetes_service_v1" resource' +- technology: ansible + component: ingress + hosting: + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", "ansible.builtin.copy", and "ansible.builtin.systemd" tasks' +- technology: terraform + component: ingress + hosting: + - local.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"local_file" resource to create the installation script and "terraform_data" to execute the script using the "local-exec" provisioner' - technology: ansible component: ingress hosting: @@ -214,6 +235,20 @@ - kubernetes.cluster weight: 0 reason: Ansible is more specialized. +- technology: ansible + component: mysql.database + hosting: + - mysql.dbms + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. +- technology: terraform + component: mysql.database + hosting: + - mysql.dbms + - local.machine + weight: 1 + reason: Terraform provides a declarative module. - technology: ansible component: mysql.database hosting: @@ -354,20 +389,6 @@ weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' -- technology: ansible - component: bucket - artifact: cache.image - hosting: - - gcp.memorystore - weight: 0.5 - reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. -- technology: terraform - component: redis.server - artifact: cache.image - hosting: - - gcp.memorystore - weight: 1 - reason: Terraform provides a declarative module. - technology: ansible component: redis.server artifact: cache.image @@ -422,6 +443,13 @@ weight: 0.5 reason: Docker Compose is more specialized. details: '"docker_container" and "docker_image" resources' +- technology: terraform + component: redis.server + artifact: cache.image + hosting: + - gcp.memorystore + weight: 1 + reason: Terraform provides a declarative module. - technology: ansible component: redis.server artifact: cache.image @@ -582,15 +610,6 @@ weight: 1 reason: Terraform provides a declarative module. details: '"google_app_engine_standard_app_version", "google_project_iam_member", "google_service_account", "google_storage_bucket", and "google_storage_bucket_object" resources' -- technology: ansible - component: software.application - artifact: apt.package - hosting: - - '*' - - remote.machine - weight: 1 - reason: Primary use case due to the specialization of Ansible. - details: '"ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements' - technology: terraform component: software.application artifact: apt.archive @@ -620,46 +639,55 @@ details: '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts' - technology: ansible component: software.application - artifact: tar.archive + artifact: apt.package hosting: - '*' - remote.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. + details: '"ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements' +- technology: ansible + component: software.application + artifact: tar.archive + hosting: + - '*' + - local.machine weight: 0.5 - reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application". - details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' + reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. + details: '"ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' - technology: terraform component: software.application artifact: tar.archive hosting: - '*' - - remote.machine + - local.machine weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' + details: '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts' - technology: ansible component: software.application artifact: tar.archive hosting: - '*' - - local.machine + - remote.machine weight: 0.5 - reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. - details: '"ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' + reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., "service.application". + details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' - technology: terraform component: software.application artifact: tar.archive hosting: - '*' - - local.machine + - remote.machine weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts' + details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' - technology: ansible component: software.application artifact: zip.archive hosting: - '*' - - remote.machine + - local.machine weight: 0.5 reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. details: '"ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' @@ -668,16 +696,16 @@ artifact: zip.archive hosting: - '*' - - remote.machine + - local.machine weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' + details: '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts' - technology: ansible component: software.application artifact: zip.archive hosting: - '*' - - local.machine + - remote.machine weight: 0.5 reason: While this is a primary use case due to the specialization of Ansible, we must rely on scripts. More specialized types should be used, e.g., service.application. details: '"ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements' @@ -686,10 +714,10 @@ artifact: zip.archive hosting: - '*' - - local.machine + - remote.machine weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts' + details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' - technology: ansible component: virtual.machine artifact: machine.image diff --git a/src/technologies/plugins/rules/registry.ts b/src/technologies/plugins/rules/registry.ts index b3594097a5..cd7262b3d9 100644 --- a/src/technologies/plugins/rules/registry.ts +++ b/src/technologies/plugins/rules/registry.ts @@ -1,3 +1,5 @@ +import * as assert from '#assert' +import * as check from '#check' import {TechnologyRule} from '#spec/technology-template' import generators from '#technologies/plugins/rules/generators' import {constructRuleName} from '#technologies/utils' @@ -23,24 +25,52 @@ class Registry { } } + private _rules: TechnologyRule[] | undefined get rules(): TechnologyRule[] { - const list: TechnologyRule[] = [] - - for (const generator of this.map.values()) { - list.push( - utils.copy({ - technology: generator.technology, - component: generator.component, - artifact: generator.artifact, - hosting: generator.hosting, - weight: generator.weight, - reason: generator.reason, - details: generator.details, - }) - ) + if (check.isUndefined(this._rules)) { + const list: TechnologyRule[] = [] + + for (const generator of this.map.values()) { + list.push( + utils.copy({ + technology: generator.technology, + component: generator.component, + artifact: generator.artifact, + hosting: generator.hosting, + weight: generator.weight, + reason: generator.reason, + details: generator.details, + }) + ) + } + + list.sort((x, y) => { + assert.isDefined(x.hosting) + assert.isDefined(y.hosting) + + // Sort by component + const c = x.component.localeCompare(y.component) + if (c !== 0) return c + + // Sort by artifact + let a = 0 + if (check.isDefined(x.artifact) && check.isDefined(y.artifact)) { + a = x.artifact.localeCompare(y.artifact) + } + if (a !== 0) return a + + // Sort by hosting stack + const h = x.hosting.join().localeCompare(y.hosting.join()) + if (h !== 0) return h + + // Sort by technology + return x.component.localeCompare(y.component) + }) + + this._rules = list } - return list + return this._rules } } diff --git a/tasks/docs/generate/rules/template.ejs b/tasks/docs/generate/rules/template.ejs index ccec3b09f5..00169def04 100644 --- a/tasks/docs/generate/rules/template.ejs +++ b/tasks/docs/generate/rules/template.ejs @@ -90,6 +90,7 @@ This appendix contains the deployment technology rules. <% if (rule.artifact) {-%> | Artifact | <%= link(rule.artifact) %> | <% } -%> +| Technology | <%= rule.technology %> | <% if (rule.hosting.length !== 0) {-%> | Hosting | <%= rule.hosting.map(link).join(" -> ") %> | <% } -%> From 7e019aa0f6b2197fc10a91331e779f0a6dc84867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Sun, 8 Sep 2024 16:03:14 +0200 Subject: [PATCH 13/18] minor --- tasks/docs/generate/rules/template.ejs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/docs/generate/rules/template.ejs b/tasks/docs/generate/rules/template.ejs index 00169def04..f9748218ab 100644 --- a/tasks/docs/generate/rules/template.ejs +++ b/tasks/docs/generate/rules/template.ejs @@ -10,7 +10,7 @@ tags: # Deployment Technology Rules Specification 1.0 Release Candidate !!! info - Elements in graphs can be clicked to open their type definition! + Quick Tip: Elements in graphs can be clicked to open their type definition! {{ autogenerated_notice('./task docs:generate:rules') }} From d2e52becac6bc6dba4fbb7d247aed61143447dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Sun, 8 Sep 2024 16:15:30 +0200 Subject: [PATCH 14/18] continue --- docs/docs/variability4tosca/rules/index.md | 132 ++++++++++-- .../rules/technology-rules.yaml | 38 +++- .../machine/local-machine/terraform/index.ts | 2 +- .../machine/local-machine/terraform/index.ts | 2 +- .../tar-archive/asterisk/index.ts | 6 +- .../tar-archive/asterisk/machine/index.ts | 4 + .../machine/local-machine/ansible/index.ts | 130 +++++++++++ .../local-machine}/index.ts | 0 .../machine/local-machine/terraform/index.ts | 203 ++++++++++++++++++ .../remote-machine/ansible/index.ts | 0 .../asterisk/machine}/remote-machine/index.ts | 0 .../remote-machine/terraform/index.ts | 0 .../zip-archive/asterisk/index.ts | 6 +- .../zip-archive/asterisk/machine/index.ts | 4 + .../machine/local-machine/ansible/index.ts | 137 ++++++++++++ .../asterisk/machine/local-machine/index.ts | 4 + .../machine/local-machine/terraform/index.ts | 203 ++++++++++++++++++ .../remote-machine/ansible/index.ts | 0 .../asterisk/machine/remote-machine/index.ts | 4 + .../remote-machine/terraform/index.ts | 0 .../machine/local-machine/terraform/index.ts | 2 +- .../machine/local-machine/terraform/index.ts | 2 +- .../machine/local-machine/terraform/index.ts | 4 +- tasks/docs/generate/rules/template.ejs | 4 +- 24 files changed, 847 insertions(+), 40 deletions(-) create mode 100644 src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts rename src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/{remote-machine => machine/local-machine}/index.ts (100%) create mode 100644 src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts rename src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/{ => machine}/remote-machine/ansible/index.ts (100%) rename src/technologies/plugins/rules/generators/service-application/{zip-archive/asterisk => tar-archive/asterisk/machine}/remote-machine/index.ts (100%) rename src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/{ => machine}/remote-machine/terraform/index.ts (100%) create mode 100644 src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts create mode 100644 src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/local-machine/index.ts create mode 100644 src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts rename src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/{ => machine}/remote-machine/ansible/index.ts (100%) create mode 100644 src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/remote-machine/index.ts rename src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/{ => machine}/remote-machine/terraform/index.ts (100%) diff --git a/docs/docs/variability4tosca/rules/index.md b/docs/docs/variability4tosca/rules/index.md index 5ab3014b9f..3163a8570b 100644 --- a/docs/docs/variability4tosca/rules/index.md +++ b/docs/docs/variability4tosca/rules/index.md @@ -10,7 +10,7 @@ tags: # Deployment Technology Rules Specification 1.0 Release Candidate !!! info - Elements in graphs can be clicked to open their type definition! + Quick Tip: Elements in graphs can be clicked to open their type definition! {{ autogenerated_notice('./task docs:generate:rules') }} @@ -643,6 +643,23 @@ The node template is hosted on the node template "host 1" of node type [kubernet ### Scenario #5 +In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [tar.archive](/normative#tararchive){target=_blank}. +The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(service.application)artifact(tar.archive)...host 2(local.machine)hosthost
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. Special integration for systemd. + +!!! failure "Terraform (Quality: 0)" + Ansible is more specialized. Also using provisioners is a "last resort". + + + +### Scenario #6 + In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [tar.archive](/normative#tararchive){target=_blank}. The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [remote.machine](/normative#remotemachine){target=_blank}. @@ -658,7 +675,24 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w -### Scenario #6 +### Scenario #7 + +In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. +This node template is implemented by its deployment artifact "artifact" of artifact type [zip.archive](/normative#ziparchive){target=_blank}. +The node template is hosted on an arbitrary hosting stack of arbitrary length, which is hosted on the node template "host 2" of node type [local.machine](/normative#localmachine){target=_blank}. + +
component(service.application)artifact(zip.archive)...host 2(local.machine)hosthost
+ + +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. Special integration for systemd. + +!!! failure "Terraform (Quality: 0)" + Ansible is more specialized. Also using provisioners is a "last resort". + + + +### Scenario #8 In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [zip.archive](/normative#ziparchive){target=_blank}. @@ -675,7 +709,7 @@ The node template is hosted on an arbitrary hosting stack of arbitrary length, w -### Scenario #7 +### Scenario #9 In this scenario, the node template "component" of node type [service.application](/normative#serviceapplication){target=_blank} is deployed. This node template is implemented by its deployment artifact "artifact" of artifact type [zip.archive](/normative#ziparchive){target=_blank}. @@ -1738,6 +1772,32 @@ This appendix contains the deployment technology rules. ### Rule #73 | Attribute | Value | | --- | --- | +| Identifier | service.application#tar.archive::ansible@*->local.machine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [tar.archive](/normative#tararchive){target=_blank} | +| Technology | ansible | +| Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. Special integration for systemd. | +| Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements | +| Graph |
component(service.application)artifact(tar.archive)...host 2(local.machine)hosthost
| + +### Rule #74 +| Attribute | Value | +| --- | --- | +| Identifier | service.application#tar.archive::terraform@*->local.machine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [tar.archive](/normative#tararchive){target=_blank} | +| Technology | terraform | +| Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0 | +| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | +| Details | "local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts. | +| Graph |
component(service.application)artifact(tar.archive)...host 2(local.machine)hosthost
| + +### Rule #75 +| Attribute | Value | +| --- | --- | | Identifier | service.application#tar.archive::ansible@*->remote.machine | | Component | [service.application](/normative#serviceapplication){target=_blank} | | Artifact | [tar.archive](/normative#tararchive){target=_blank} | @@ -1748,7 +1808,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements | | Graph |
component(service.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #74 +### Rule #76 | Attribute | Value | | --- | --- | | Identifier | service.application#tar.archive::terraform@*->remote.machine | @@ -1761,7 +1821,33 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(service.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #75 +### Rule #77 +| Attribute | Value | +| --- | --- | +| Identifier | service.application#zip.archive::ansible@*->local.machine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Technology | ansible | +| Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. Special integration for systemd. | +| Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements | +| Graph |
component(service.application)artifact(zip.archive)...host 2(local.machine)hosthost
| + +### Rule #78 +| Attribute | Value | +| --- | --- | +| Identifier | service.application#zip.archive::terraform@*->local.machine | +| Component | [service.application](/normative#serviceapplication){target=_blank} | +| Artifact | [zip.archive](/normative#ziparchive){target=_blank} | +| Technology | terraform | +| Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | +| Quality | 0 | +| Reason | Ansible is more specialized. Also using provisioners is a "last resort". | +| Details | "local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts. | +| Graph |
component(service.application)artifact(zip.archive)...host 2(local.machine)hosthost
| + +### Rule #79 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::ansible@*->remote.machine | @@ -1774,7 +1860,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements | | Graph |
component(service.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #76 +### Rule #80 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::terraform@*->remote.machine | @@ -1787,7 +1873,7 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(service.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #77 +### Rule #81 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::ansible@gcp.appengine | @@ -1800,7 +1886,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.shell", "ansible.builtin.tempfile", "ansible.builtin.unarchive", and "ansible.builtin.copy" tasks | | Graph |
component(service.application)artifact(zip.archive)host 1(gcp.appengine)host
| -### Rule #78 +### Rule #82 | Attribute | Value | | --- | --- | | Identifier | service.application#zip.archive::terraform@gcp.appengine | @@ -1813,7 +1899,7 @@ This appendix contains the deployment technology rules. | Details | "google_app_engine_standard_app_version", "google_project_iam_member", "google_service_account", "google_storage_bucket", and "google_storage_bucket_object" resources | | Graph |
component(service.application)artifact(zip.archive)host 1(gcp.appengine)host
| -### Rule #79 +### Rule #83 | Attribute | Value | | --- | --- | | Identifier | software.application#apt.archive::terraform@*->remote.machine | @@ -1826,7 +1912,7 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload scripts and "remote-exec" to execute scripts | | Graph |
component(software.application)artifact(apt.archive)...host 2(remote.machine)hosthost
| -### Rule #80 +### Rule #84 | Attribute | Value | | --- | --- | | Identifier | software.application#apt.package::ansible@*->local.machine | @@ -1839,7 +1925,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements | | Graph |
component(software.application)artifact(apt.package)...host 2(local.machine)hosthost
| -### Rule #81 +### Rule #85 | Attribute | Value | | --- | --- | | Identifier | software.application#apt.package::terraform@*->local.machine | @@ -1852,7 +1938,7 @@ This appendix contains the deployment technology rules. | Details | "local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts | | Graph |
component(software.application)artifact(apt.package)...host 2(local.machine)hosthost
| -### Rule #82 +### Rule #86 | Attribute | Value | | --- | --- | | Identifier | software.application#apt.package::ansible@*->remote.machine | @@ -1865,7 +1951,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.shell", "ansible.builtin.apt_key", "ansible.builtin.apt_repository", "ansible.builtin.apt", and "ansible.builtin.copy", tasks with "when" statements | | Graph |
component(software.application)artifact(apt.package)...host 2(remote.machine)hosthost
| -### Rule #83 +### Rule #87 | Attribute | Value | | --- | --- | | Identifier | software.application#tar.archive::ansible@*->local.machine | @@ -1878,7 +1964,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | | Graph |
component(software.application)artifact(tar.archive)...host 2(local.machine)hosthost
| -### Rule #84 +### Rule #88 | Attribute | Value | | --- | --- | | Identifier | software.application#tar.archive::terraform@*->local.machine | @@ -1891,7 +1977,7 @@ This appendix contains the deployment technology rules. | Details | "local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts | | Graph |
component(software.application)artifact(tar.archive)...host 2(local.machine)hosthost
| -### Rule #85 +### Rule #89 | Attribute | Value | | --- | --- | | Identifier | software.application#tar.archive::ansible@*->remote.machine | @@ -1904,7 +1990,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | | Graph |
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #86 +### Rule #90 | Attribute | Value | | --- | --- | | Identifier | software.application#tar.archive::terraform@*->remote.machine | @@ -1917,7 +2003,7 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(software.application)artifact(tar.archive)...host 2(remote.machine)hosthost
| -### Rule #87 +### Rule #91 | Attribute | Value | | --- | --- | | Identifier | software.application#zip.archive::ansible@*->local.machine | @@ -1930,7 +2016,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | | Graph |
component(software.application)artifact(zip.archive)...host 2(local.machine)hosthost
| -### Rule #88 +### Rule #92 | Attribute | Value | | --- | --- | | Identifier | software.application#zip.archive::terraform@*->local.machine | @@ -1940,10 +2026,10 @@ This appendix contains the deployment technology rules. | Hosting | * -> [local.machine](/normative#localmachine){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. Also using provisioners is a "last resort". | -| Details | "local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts | +| Details | "local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts. | | Graph |
component(software.application)artifact(zip.archive)...host 2(local.machine)hosthost
| -### Rule #89 +### Rule #93 | Attribute | Value | | --- | --- | | Identifier | software.application#zip.archive::ansible@*->remote.machine | @@ -1956,7 +2042,7 @@ This appendix contains the deployment technology rules. | Details | "ansible.builtin.apt", "ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", and "ansible.builtin.shell" tasks with "when" statements | | Graph |
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #90 +### Rule #94 | Attribute | Value | | --- | --- | | Identifier | software.application#zip.archive::terraform@*->remote.machine | @@ -1969,7 +2055,7 @@ This appendix contains the deployment technology rules. | Details | "file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts | | Graph |
component(software.application)artifact(zip.archive)...host 2(remote.machine)hosthost
| -### Rule #91 +### Rule #95 | Attribute | Value | | --- | --- | | Identifier | virtual.machine#machine.image::ansible@openstack.provider | @@ -1982,7 +2068,7 @@ This appendix contains the deployment technology rules. | Details | "openstack.cloud.security_group", "openstack.cloud.security_group_rule" and "openstack.cloud.server" tasks | | Graph |
component(virtual.machine)artifact(machine.image)host 1(openstack.provider)host
| -### Rule #92 +### Rule #96 | Attribute | Value | | --- | --- | | Identifier | virtual.machine#machine.image::terraform@openstack.provider | diff --git a/docs/docs/variability4tosca/rules/technology-rules.yaml b/docs/docs/variability4tosca/rules/technology-rules.yaml index c70c424dcc..cfd78be74a 100644 --- a/docs/docs/variability4tosca/rules/technology-rules.yaml +++ b/docs/docs/variability4tosca/rules/technology-rules.yaml @@ -558,6 +558,24 @@ weight: 0.5 reason: Kubernetes is more specialized. details: '"kubernetes_deployment_v1" and "kubernetes_service_v1" resources' +- technology: ansible + component: service.application + artifact: tar.archive + hosting: + - '*' + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. Special integration for systemd. + details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements' +- technology: terraform + component: service.application + artifact: tar.archive + hosting: + - '*' + - local.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts.' - technology: ansible component: service.application artifact: tar.archive @@ -576,6 +594,24 @@ weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". details: '"file" provisioner to upload artifacts and scripts and "remote-exec" to execute scripts' +- technology: ansible + component: service.application + artifact: zip.archive + hosting: + - '*' + - local.machine + weight: 1 + reason: Primary use case due to the specialization of Ansible. Special integration for systemd. + details: '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements' +- technology: terraform + component: service.application + artifact: zip.archive + hosting: + - '*' + - local.machine + weight: 0 + reason: Ansible is more specialized. Also using provisioners is a "last resort". + details: '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts.' - technology: ansible component: service.application artifact: zip.archive @@ -699,7 +735,7 @@ - local.machine weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts' + details: '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts.' - technology: ansible component: software.application artifact: zip.archive diff --git a/src/technologies/plugins/rules/generators/ingress/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/ingress/machine/local-machine/terraform/index.ts index ec6f62e27e..83c9bfff13 100644 --- a/src/technologies/plugins/rules/generators/ingress/machine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/ingress/machine/local-machine/terraform/index.ts @@ -39,7 +39,7 @@ const generator: ImplementationGenerator = { }, }, terraform_data: { - vm: [ + local: [ { depends_on: ['local_file.tmp_script'], provisioner: { diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/terraform/index.ts index 29faa09995..932d6d3539 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/terraform/index.ts @@ -62,7 +62,7 @@ const generator: ImplementationGenerator = { }, }, terraform_data: { - vm: [ + local: [ { depends_on: 'local_file.tmp_script', provisioner: { diff --git a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/index.ts b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/index.ts index dfab123584..e5b39e1579 100644 --- a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/index.ts @@ -1,5 +1,3 @@ -import remoteMachine from './remote-machine' +import machine from './machine' -// TODO: local machine - -export default [remoteMachine] +export default [machine] diff --git a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/index.ts b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/index.ts new file mode 100644 index 0000000000..2e2d177edd --- /dev/null +++ b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/index.ts @@ -0,0 +1,4 @@ +import localMachine from './local-machine' +import remoteMachine from './remote-machine' + +export default [remoteMachine, localMachine] diff --git a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts new file mode 100644 index 0000000000..402239dae5 --- /dev/null +++ b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/local-machine/ansible/index.ts @@ -0,0 +1,130 @@ +import {NodeType} from '#spec/node-type' +import { + AnsibleSoftwareApplicationConfigureTasks, + AnsibleSoftwareApplicationDeleteTasks, + AnsibleSoftwareApplicationSourceArchiveCreateTasks, + AnsibleSoftwareApplicationStartTasks, + AnsibleSoftwareApplicationStopTasks, +} from '#technologies/plugins/rules/generators/software-application/utils' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import { + AnsibleCreateApplicationSystemdUnit, + AnsibleDeleteApplicationSystemdUnit, + AnsibleEnableApplicationSystemdUnit, + AnsibleOrchestratorOperation, + AnsibleStartApplicationSystemdUnit, + AnsibleStopApplicationSystemdUnit, + AnsibleSystemdDaemonReload, +} from '#technologies/plugins/rules/utils/ansible' +import {ApplicationDirectory, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' + +class Generator extends GeneratorAbstract { + component = 'service.application' + technology = 'ansible' + artifact = 'tar.archive' + hosting = ['*', 'local.machine'] + weight = 1 + reason = 'Primary use case due to the specialization of Ansible. Special integration for systemd.' + details = + '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements' + + generate(name: string, type: NodeType) { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...ApplicationDirectory(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + ...AnsibleSoftwareApplicationSourceArchiveCreateTasks({ + type, + artifact: this.artifact, + }), + { + ...AnsibleCreateApplicationSystemdUnit(), + }, + { + ...AnsibleEnableApplicationSystemdUnit(), + }, + ], + }, + }, + }, + configure: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [...AnsibleSoftwareApplicationConfigureTasks()], + }, + }, + }, + start: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + ...AnsibleSoftwareApplicationStartTasks(), + { + ...AnsibleStartApplicationSystemdUnit(), + }, + ], + }, + }, + }, + stop: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + ...AnsibleSoftwareApplicationStopTasks(), + { + ...AnsibleStopApplicationSystemdUnit(), + }, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + ...AnsibleSoftwareApplicationDeleteTasks(), + { + ...AnsibleDeleteApplicationSystemdUnit(), + }, + { + ...AnsibleSystemdDaemonReload(), + }, + ], + }, + }, + }, + }, + }, + }, + } + } +} + +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/index.ts b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/local-machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/index.ts rename to src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/local-machine/index.ts diff --git a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts new file mode 100644 index 0000000000..d41b53f175 --- /dev/null +++ b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts @@ -0,0 +1,203 @@ +import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' +import {NodeType} from '#spec/node-type' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import { + ApplicationDirectory, + ApplicationSystemdUnit, + BASH_HEADER, + BashAssertManagementOperation, + BashCallManagementOperation, + BashCopyManagementOperation, + BashCreateApplicationDirectory, + BashCreateApplicationEnvironment, + BashCreateVintnerDirectory, + BashDeleteApplicationDirectory, + BashDownloadSourceArchive, + BashUnarchiveSourceArchiveFile, + JinjaWhenSourceArchiveFile, + MetadataGenerated, + SourceArchiveFile, +} from '#technologies/plugins/rules/utils/utils' + +class Generator extends GeneratorAbstract { + component = 'service.application' + technology = 'terraform' + artifact = 'tar.archive' + hosting = ['*', 'local.machine'] + weight = 0 + reason = 'Ansible is more specialized. Also using provisioners is a "last resort".' + details = '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts.' + + generate(name: string, type: NodeType) { + return { + derived_from: name, + metadata: {...MetadataGenerated()}, + properties: { + ...ApplicationDirectory(), + }, + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + resource: { + local_file: { + tmp_artifact: { + source: SourceArchiveFile(this.artifact), + filename: `/tmp/artifact-${name}`, + count: `{{ (${JinjaWhenSourceArchiveFile(this.artifact)}) | ternary(1, 0) }}`, + }, + tmp_service: { + content: ApplicationSystemdUnit(), + filename: '/etc/systemd/system/{{ SELF.application_name }}.service', + }, + tmp_create: { + content: this.create(name, type), + filename: `/tmp/create-${name}.sh`, + }, + tmp_configure: { + content: this.configure(), + filename: `/tmp/configure-${name}.sh`, + }, + tmp_start: { + content: this.start(), + filename: `/tmp/start-${name}.sh`, + }, + tmp_stop: { + content: this.stop(), + filename: `/tmp/stop-${name}.sh`, + }, + tmp_delete: { + content: this.delete(), + filename: `/tmp/delete-${name}.sh`, + }, + }, + terraform_data: { + local: [ + { + depends_on: [ + 'local_file.tmp_artifact', + 'local_file.tmp_service', + 'local_file.tmp_create', + 'local_file.tmp_configure', + 'local_file.tmp_start', + 'local_file.tmp_stop', + 'local_file.tmp_delete', + ], + provisioner: { + 'local-exec': [ + { + inline: [ + `sudo bash /tmp/create-${name}.sh`, + `sudo bash /tmp/configure-${name}.sh`, + `sudo bash /tmp/start-${name}.sh`, + ], + }, + { + inline: [ + `sudo bash /tmp/stop-${name}.sh`, + `sudo bash /tmp/delete-${name}.sh`, + ], + when: 'destroy', + }, + ], + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + } + + private create(name: string, type: NodeType) { + return `${BASH_HEADER} + +# Create application directory +${BashCreateApplicationDirectory()} + +# Create application environment +${BashCreateApplicationEnvironment(type)} + +# Download deployment artifact if required +${BashDownloadSourceArchive(name, this.artifact)} + +# Extract deployment artifact +${BashUnarchiveSourceArchiveFile(name, this.artifact)} + +# Create vintner directory +${BashCreateVintnerDirectory()} + +# Reload systemd daemon +systemctl daemon-reload + +# Enable service +systemctl enable {{ SELF.application_name }} +` + } + + private configure() { + return `${BASH_HEADER} + +# Copy operation +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} + +# Execute operation +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} +` + } + + private start() { + return `${BASH_HEADER} + +# Assert operation +${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.START)} + +# Start service +systemctl start {{ SELF.application_name }} +` + } + + private stop() { + return `${BASH_HEADER} + +# Assert operation +${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.STOP)} + +# Copy operation +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.STOP)} + +# Execute operation +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.STOP)} + +# Stop service +systemctl stop {{ SELF.application_name }} +` + } + + private delete() { + return `${BASH_HEADER} + +# Copy operation +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} + +# Execute operation +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} + +# Delete application directory +${BashDeleteApplicationDirectory()} + +# Delete systemd service +rm -f /etc/systemd/system/{{ SELF.application_name }}.service + +# Reload system daemon +systemctl daemon-reload +` + } +} + +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/remote-machine/ansible/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/ansible/index.ts rename to src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/remote-machine/ansible/index.ts diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/index.ts b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/remote-machine/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/index.ts rename to src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/remote-machine/index.ts diff --git a/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/remote-machine/terraform/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/remote-machine/terraform/index.ts rename to src/technologies/plugins/rules/generators/service-application/tar-archive/asterisk/machine/remote-machine/terraform/index.ts diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/index.ts b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/index.ts index dfab123584..e5b39e1579 100644 --- a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/index.ts +++ b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/index.ts @@ -1,5 +1,3 @@ -import remoteMachine from './remote-machine' +import machine from './machine' -// TODO: local machine - -export default [remoteMachine] +export default [machine] diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/index.ts b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/index.ts new file mode 100644 index 0000000000..2e2d177edd --- /dev/null +++ b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/index.ts @@ -0,0 +1,4 @@ +import localMachine from './local-machine' +import remoteMachine from './remote-machine' + +export default [remoteMachine, localMachine] diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts new file mode 100644 index 0000000000..7b029c5ac9 --- /dev/null +++ b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts @@ -0,0 +1,137 @@ +import {NodeType} from '#spec/node-type' +import { + AnsibleSoftwareApplicationConfigureTasks, + AnsibleSoftwareApplicationDeleteTasks, + AnsibleSoftwareApplicationSourceArchiveCreateTasks, + AnsibleSoftwareApplicationStartTasks, + AnsibleSoftwareApplicationStopTasks, +} from '#technologies/plugins/rules/generators/software-application/utils' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import { + AnsibleCreateApplicationSystemdUnit, + AnsibleDeleteApplicationSystemdUnit, + AnsibleEnableApplicationSystemdUnit, + AnsibleOrchestratorOperation, + AnsibleStartApplicationSystemdUnit, + AnsibleStopApplicationSystemdUnit, + AnsibleSystemdDaemonReload, +} from '#technologies/plugins/rules/utils/ansible' +import {ApplicationDirectory, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' + +class Generator extends GeneratorAbstract { + component = 'service.application' + technology = 'ansible' + artifact = 'zip.archive' + hosting = ['*', 'local.machine'] + weight = 1 + reason = 'Primary use case due to the specialization of Ansible. Special integration for systemd.' + details = + '"ansible.builtin.file", "ansible.builtin.unarchive", "ansible.builtin.copy", "ansible.builtin.fail", "ansible.builtin.shell", and "ansible.builtin.systemd" tasks with "when" statements' + + generate(name: string, type: NodeType) { + return { + derived_from: name, + metadata: { + ...MetadataGenerated(), + ...MetadataUnfurl(), + }, + properties: { + ...ApplicationDirectory(), + }, + interfaces: { + Standard: { + operations: { + create: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + { + name: 'install operational dependencies', + 'ansible.builtin.apt': { + name: 'unzip', + update_cache: 'yes', + }, + }, + ...AnsibleSoftwareApplicationSourceArchiveCreateTasks({ + type, + artifact: this.artifact, + }), + { + ...AnsibleCreateApplicationSystemdUnit(), + }, + { + ...AnsibleEnableApplicationSystemdUnit(), + }, + ], + }, + }, + }, + configure: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [...AnsibleSoftwareApplicationConfigureTasks()], + }, + }, + }, + start: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + ...AnsibleSoftwareApplicationStartTasks(), + { + ...AnsibleStartApplicationSystemdUnit(), + }, + ], + }, + }, + }, + stop: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + ...AnsibleSoftwareApplicationStopTasks(), + { + ...AnsibleStopApplicationSystemdUnit(), + }, + ], + }, + }, + }, + delete: { + implementation: { + ...AnsibleOrchestratorOperation(), + }, + inputs: { + playbook: { + q: [ + ...AnsibleSoftwareApplicationDeleteTasks(), + { + ...AnsibleDeleteApplicationSystemdUnit(), + }, + { + ...AnsibleSystemdDaemonReload(), + }, + ], + }, + }, + }, + }, + }, + }, + } + } +} + +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/local-machine/index.ts b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/local-machine/index.ts new file mode 100644 index 0000000000..c76a810960 --- /dev/null +++ b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/local-machine/index.ts @@ -0,0 +1,4 @@ +import ansible from './ansible' +import terraform from './terraform' + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts new file mode 100644 index 0000000000..bbae234023 --- /dev/null +++ b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts @@ -0,0 +1,203 @@ +import {MANAGEMENT_OPERATIONS} from '#spec/interface-definition' +import {NodeType} from '#spec/node-type' +import {GeneratorAbstract} from '#technologies/plugins/rules/types' +import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' +import { + ApplicationDirectory, + ApplicationSystemdUnit, + BASH_HEADER, + BashAssertManagementOperation, + BashCallManagementOperation, + BashCopyManagementOperation, + BashCreateApplicationDirectory, + BashCreateApplicationEnvironment, + BashCreateVintnerDirectory, + BashDeleteApplicationDirectory, + BashDownloadSourceArchive, + BashUnarchiveSourceArchiveFile, + JinjaWhenSourceArchiveFile, + MetadataGenerated, + SourceArchiveFile, +} from '#technologies/plugins/rules/utils/utils' + +class Generator extends GeneratorAbstract { + component = 'service.application' + technology = 'terraform' + artifact = 'zip.archive' + hosting = ['*', 'local.machine'] + weight = 0 + reason = 'Ansible is more specialized. Also using provisioners is a "last resort".' + details = '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts.' + + generate(name: string, type: NodeType) { + return { + derived_from: name, + metadata: {...MetadataGenerated()}, + properties: { + ...ApplicationDirectory(), + }, + interfaces: { + ...TerraformStandardOperations(), + defaults: { + inputs: { + main: { + resource: { + local_file: { + tmp_artifact: { + source: SourceArchiveFile(this.artifact), + filename: `/tmp/artifact-${name}`, + count: `{{ (${JinjaWhenSourceArchiveFile(this.artifact)}) | ternary(1, 0) }}`, + }, + tmp_service: { + content: ApplicationSystemdUnit(), + filename: '/etc/systemd/system/{{ SELF.application_name }}.service', + }, + tmp_create: { + content: this.create(name, type), + filename: `/tmp/create-${name}.sh`, + }, + tmp_configure: { + content: this.configure(), + filename: `/tmp/configure-${name}.sh`, + }, + tmp_start: { + content: this.start(), + filename: `/tmp/start-${name}.sh`, + }, + tmp_stop: { + content: this.stop(), + filename: `/tmp/stop-${name}.sh`, + }, + tmp_delete: { + content: this.delete(), + filename: `/tmp/delete-${name}.sh`, + }, + }, + terraform_data: { + local: [ + { + depends_on: [ + 'local_file.tmp_artifact', + 'local_file.tmp_service', + 'local_file.tmp_create', + 'local_file.tmp_configure', + 'local_file.tmp_start', + 'local_file.tmp_stop', + 'local_file.tmp_delete', + ], + provisioner: { + 'local-exec': [ + { + inline: [ + `sudo bash /tmp/create-${name}.sh`, + `sudo bash /tmp/configure-${name}.sh`, + `sudo bash /tmp/start-${name}.sh`, + ], + }, + { + inline: [ + `sudo bash /tmp/stop-${name}.sh`, + `sudo bash /tmp/delete-${name}.sh`, + ], + when: 'destroy', + }, + ], + }, + }, + ], + }, + }, + }, + }, + }, + }, + } + } + + private create(name: string, type: NodeType) { + return `${BASH_HEADER} + +# Create application directory +${BashCreateApplicationDirectory()} + +# Create application environment +${BashCreateApplicationEnvironment(type)} + +# Download deployment artifact if required +${BashDownloadSourceArchive(name, this.artifact)} + +# Extract deployment artifact +${BashUnarchiveSourceArchiveFile(name, this.artifact)} + +# Create vintner directory +${BashCreateVintnerDirectory()} + +# Reload systemd daemon +systemctl daemon-reload + +# Enable service +systemctl enable {{ SELF.application_name }} +` + } + + private configure() { + return `${BASH_HEADER} + +# Copy operation +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} + +# Execute operation +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.CONFIGURE)} +` + } + + private start() { + return `${BASH_HEADER} + +# Assert operation +${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.START)} + +# Start service +systemctl start {{ SELF.application_name }} +` + } + + private stop() { + return `${BASH_HEADER} + +# Assert operation +${BashAssertManagementOperation(MANAGEMENT_OPERATIONS.STOP)} + +# Copy operation +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.STOP)} + +# Execute operation +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.STOP)} + +# Stop service +systemctl stop {{ SELF.application_name }} +` + } + + private delete() { + return `${BASH_HEADER} + +# Copy operation +${BashCopyManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} + +# Execute operation +${BashCallManagementOperation(MANAGEMENT_OPERATIONS.DELETE)} + +# Delete application directory +${BashDeleteApplicationDirectory()} + +# Delete systemd service +rm -f /etc/systemd/system/{{ SELF.application_name }}.service + +# Reload system daemon +systemctl daemon-reload +` + } +} + +export default new Generator() diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/remote-machine/ansible/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/ansible/index.ts rename to src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/remote-machine/ansible/index.ts diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/remote-machine/index.ts b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/remote-machine/index.ts new file mode 100644 index 0000000000..c76a810960 --- /dev/null +++ b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/remote-machine/index.ts @@ -0,0 +1,4 @@ +import ansible from './ansible' +import terraform from './terraform' + +export default [ansible, terraform] diff --git a/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/remote-machine/terraform/index.ts similarity index 100% rename from src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/remote-machine/terraform/index.ts rename to src/technologies/plugins/rules/generators/service-application/zip-archive/asterisk/machine/remote-machine/terraform/index.ts diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/terraform/index.ts index 791b63d904..3ecbd8053b 100644 --- a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/terraform/index.ts @@ -71,7 +71,7 @@ class Generator extends GeneratorAbstract { }, }, terraform_data: { - vm: [ + local: [ { provisioner: { depends_on: [ diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts index fce8a22d25..798b9f1860 100644 --- a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts @@ -73,7 +73,7 @@ class Generator extends GeneratorAbstract { }, }, terraform_data: { - vm: [ + local: [ { depends_on: [ 'local_file.tmp_artifact', diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts index 4055b5c7a5..616a382ecc 100644 --- a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts @@ -24,7 +24,7 @@ class Generator extends GeneratorAbstract { hosting = ['*', 'local.machine'] weight = 0 reason = 'Ansible is more specialized. Also using provisioners is a "last resort".' - details = '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts' + details = '"local_file" module to create scripts and artifacts and "local-exec" provisioner to execute scripts.' generate(name: string, type: NodeType) { return { @@ -73,7 +73,7 @@ class Generator extends GeneratorAbstract { }, }, terraform_data: { - vm: [ + local: [ { depends_on: [ 'local_file.tmp_artifact', diff --git a/tasks/docs/generate/rules/template.ejs b/tasks/docs/generate/rules/template.ejs index f9748218ab..a01d29a242 100644 --- a/tasks/docs/generate/rules/template.ejs +++ b/tasks/docs/generate/rules/template.ejs @@ -9,8 +9,8 @@ tags: # Deployment Technology Rules Specification 1.0 Release Candidate -!!! info - Quick Tip: Elements in graphs can be clicked to open their type definition! +!!! info "Quick Tip" + Elements in graphs can be clicked to open their type definition! {{ autogenerated_notice('./task docs:generate:rules') }} From 5ca65a70298ba8cdbc032aebf359ff2e8131214b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Sun, 8 Sep 2024 17:20:49 +0200 Subject: [PATCH 15/18] drop industry --- .../lib/retailer.yaml | 31264 ---------------- .../lib/tosca-vintner-profile-core.yaml | 2502 -- .../lib/tosca-vintner-profile-extended.yaml | 16192 -------- .../lib/tosca-vintner-profile.yaml | 21 - .../lib/types.yaml | 4 - .../scripts/clean.sh | 11 - .../scripts/code.sh | 11 - .../scripts/configuration.env | 5 - .../scripts/configuration.sh | 36 - .../scripts/continue.sh | 11 - .../scripts/deploy.sh | 16 - .../scripts/enrich.sh | 8 - .../scripts/implement.sh | 8 - .../scripts/pull.sh | 9 - .../scripts/quality.sh | 13 - .../scripts/reimport.sh | 20 - .../scripts/setup.sh | 14 - .../scripts/study-001.txt | 107 - .../scripts/study-002.txt | 106 - .../scripts/study-003.txt | 106 - .../scripts/study-004.txt | 106 - .../scripts/study-005.txt | 107 - .../scripts/study-006.txt | 107 - .../scripts/study-007.txt | 116 - .../scripts/study.sh | 8 - .../scripts/swap-lib.sh | 16 - .../scripts/undeploy.sh | 11 - .../scripts/unimplement.sh | 9 - .../study.yaml | 6 - .../tests/customer/expected.yaml | 1 - .../tests/customer/inputs.yaml | 1 - .../tests/development/expected.yaml | 1 - .../tests/development/inputs.yaml | 1 - .../tests/hyperscaler/expected.yaml | 1 - .../tests/hyperscaler/inputs.yaml | 1 - .../tests/local/expected.yaml | 1 - .../tests/local/inputs.yaml | 1 - .../variable-service-template.yaml | 882 - 38 files changed, 51840 deletions(-) delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/lib/retailer.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/lib/types.yaml delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/clean.sh delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/code.sh delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.env delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.sh delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/continue.sh delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/deploy.sh delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/enrich.sh delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/implement.sh delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/pull.sh delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/reimport.sh delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/setup.sh delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-001.txt delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-002.txt delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-003.txt delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-004.txt delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-005.txt delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-006.txt delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-007.txt delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study.sh delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/swap-lib.sh delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/undeploy.sh delete mode 100755 examples/unfurl-technology---industry---plus-maintenance-automated/scripts/unimplement.sh delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/study.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/expected.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/inputs.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/expected.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/inputs.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/expected.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/inputs.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/expected.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/inputs.yaml delete mode 100644 examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/retailer.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/retailer.yaml deleted file mode 100644 index 4e71d634ec..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/retailer.yaml +++ /dev/null @@ -1,31264 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_3 - -imports: - - ../tosca-vintner-profile.yaml - -node_types: - retailer.frontend.dashboard: - derived_from: reactjs.service.application - - retailer.frontend.terminal: - derived_from: reactjs.service.application - - retailer.service.gateway: - derived_from: nodejs.service.application - - retailer.service.core: - derived_from: nodejs.service.application - - retailer.service.jobs: - derived_from: nodejs.service.application - - retailer.service.stores: - derived_from: nodejs.service.application - - retailer.service.products: - derived_from: nodejs.service.application - - retailer.service.stocks: - derived_from: nodejs.service.application - - retailer.service.orders: - derived_from: nodejs.service.application - - retailer.service.global: - derived_from: nodejs.service.application - - # [OPENTOSCA_VINTNER_GENERATION_MARK] - - ################################################################ - # - # WARNING: Do not edit! This following content is autogenerated! - # - ################################################################ - - retailer.frontend.dashboard~service.application#docker.image::ansible@docker.engine->local.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: stop container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - state: absent - retailer.frontend.dashboard~service.application#docker.image::ansible@docker.engine->remote.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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 }}' - retailer.frontend.dashboard~service.application#docker.image::ansible@gcp.cloudrun: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: touch service - register: service - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.service.yaml' - - name: create service - ansible.builtin.copy: - dest: '{{ service.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - apiVersion: serving.knative.dev/v1 - kind: Service - metadata: - name: '{{ SELF.application_name }}' - labels: - cloud.googleapis.com/location: '{{ SELF.gcp_region }}' - annotations: - run.googleapis.com/ingress: all - spec: - template: - spec: - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - containerPort: '{{ SELF.application_port }}' - env: [] - - name: apply service - ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet - args: - executable: /bin/bash - - name: touch policy - register: policy - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.policy.yaml' - - name: fill policy - ansible.builtin.copy: - dest: '{{ policy.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - bindings: - - members: - - allUsers - role: roles/run.invoker - - name: apply policy - ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - - name: describe service - register: service_description - ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - retailer.frontend.dashboard~service.application#docker.image::ansible@kubernetes.cluster: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: create deployment - kubernetes.core.k8s: - wait: true - definition: - 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 }}' - - name: create service - kubernetes.core.k8s: - definition: - 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 - 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 }}' - retailer.frontend.dashboard~service.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.frontend.dashboard~service.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.frontend.dashboard~service.application#zip.archive::ansible@gcp.appengine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: enable GCP AppEngine - ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - register: app_create_command - failed_when: - - "'Created' not in app_create_command.stderr" - - "'already contains' not in app_create_command.stderr" - - name: create working directory - register: directory - ansible.builtin.tempfile: - state: directory - - name: extract deployment artifact in working directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ directory.path }}' - - name: create specification - ansible.builtin.copy: - dest: '{{ directory.path }}/app.yaml' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - instance_class: F1 - env_variables: {} - - name: create app - ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet - args: - executable: /bin/bash - - name: browse app - register: browse_app - ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ browse_app.stdout[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet - args: - executable: /bin/bash - retailer.frontend.dashboard~software.application#apt.package::ansible@*->remote.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.frontend.dashboard~software.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.frontend.dashboard~software.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.frontend.dashboard~service.application#docker.image::terraform@docker.engine->local.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: unix:///var/run/docker.sock - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.frontend.dashboard~service.application#docker.image::terraform@docker.engine->remote.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 - ssh_opts: - - '-i' - - '{{ SELF.os_ssh_key_file }}' - - '-o' - - IdentitiesOnly=yes - - '-o' - - BatchMode=yes - - '-o' - - UserKnownHostsFile=/dev/null - - '-o' - - StrictHostKeyChecking=no - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.frontend.dashboard~service.application#docker.image::terraform@gcp.cloudrun: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' - resource: - google_cloud_run_v2_service: - application: - - ingress: INGRESS_TRAFFIC_ALL - location: '{{ SELF.gcp_region }}' - name: '{{ SELF.application_name }}' - template: - - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - container_port: '{{ SELF.application_port }}' - env: [] - google_cloud_run_service_iam_binding: - application: - - location: '{{ SELF.gcp_region }}' - members: - - allUsers - role: roles/run.invoker - service: '{{ SELF.application_name }}' - retailer.frontend.dashboard~service.application#docker.image::terraform@kubernetes.cluster: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - kubernetes: - source: hashicorp/kubernetes - version: 2.31.0 - required_version: '>= 0.14.0' - provider: - kubernetes: - - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} - client_key: ${file("{{ SELF.k8s_client_key_file }}")} - cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} - host: '{{ SELF.k8s_host }}' - resource: - kubernetes_deployment_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - selector: - - match_labels: - app: '{{ SELF.application_name }}' - template: - - metadata: - - labels: - app: '{{ SELF.application_name }}' - spec: - - container: - - env: [] - image: '{{ ".artifacts::docker_image::file" | eval }}' - name: '{{ SELF.application_name }}' - port: - - container_port: '{{ SELF.application_port }}' - kubernetes_service_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - port: - - name: '{{ SELF.application_protocol }}' - port: '{{ SELF.application_port }}' - target_port: '{{ SELF.application_port }}' - selector: - app: '{{ SELF.application_name }}' - type: ClusterIP - retailer.frontend.dashboard~service.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.frontend.dashboard - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.frontend.dashboard {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.frontend.dashboard -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.frontend.dashboard.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.frontend.dashboard.sh - - sudo bash /tmp/configure-retailer.frontend.dashboard.sh - - sudo bash /tmp/start-retailer.frontend.dashboard.sh - - inline: - - sudo bash /tmp/stop-retailer.frontend.dashboard.sh - - sudo bash /tmp/delete-retailer.frontend.dashboard.sh - when: destroy - retailer.frontend.dashboard~service.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.frontend.dashboard - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.frontend.dashboard {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.frontend.dashboard -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.frontend.dashboard.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.frontend.dashboard.sh - - sudo bash /tmp/configure-retailer.frontend.dashboard.sh - - sudo bash /tmp/start-retailer.frontend.dashboard.sh - - inline: - - sudo bash /tmp/stop-retailer.frontend.dashboard.sh - - sudo bash /tmp/delete-retailer.frontend.dashboard.sh - when: destroy - retailer.frontend.dashboard~service.application#zip.archive::terraform@gcp.appengine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' - resource: - google_app_engine_standard_app_version: - app: - - delete_service_on_destroy: true - deployment: - - zip: - - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} - entrypoint: - - shell: '{{ SELF._management_start }}' - env_variables: {} - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - service_account: ${google_service_account.custom_service_account.email} - version_id: v1 - google_project_iam_member: - gae_api: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/compute.networkUser - storage_viewer: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/storage.objectViewer - google_service_account: - custom_service_account: - - account_id: '{{ SELF.application_name }}-account' - display_name: Custom Service Account - google_storage_bucket: - bucket: - - location: EU - name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' - google_storage_bucket_object: - object: - - bucket: ${google_storage_bucket.bucket.name} - name: object.zip - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - retailer.frontend.dashboard~software.application#apt.archive::terraform@*->remote.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.frontend.dashboard {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-retailer.frontend.dashboard.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.frontend.dashboard.sh - - sudo bash /tmp/configure-retailer.frontend.dashboard.sh - - sudo bash /tmp/start-retailer.frontend.dashboard.sh - - inline: - - sudo bash /tmp/stop-retailer.frontend.dashboard.sh - - sudo bash /tmp/delete-retailer.frontend.dashboard.sh - when: destroy - retailer.frontend.dashboard~software.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.frontend.dashboard - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.frontend.dashboard {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.frontend.dashboard -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.frontend.dashboard.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.frontend.dashboard.sh - - sudo bash /tmp/configure-retailer.frontend.dashboard.sh - - sudo bash /tmp/start-retailer.frontend.dashboard.sh - - inline: - - sudo bash /tmp/stop-retailer.frontend.dashboard.sh - - sudo bash /tmp/delete-retailer.frontend.dashboard.sh - when: destroy - retailer.frontend.dashboard~software.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.frontend.dashboard - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.frontend.dashboard {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.frontend.dashboard -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.frontend.dashboard.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.frontend.dashboard.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.frontend.dashboard.sh - - sudo bash /tmp/configure-retailer.frontend.dashboard.sh - - sudo bash /tmp/start-retailer.frontend.dashboard.sh - - inline: - - sudo bash /tmp/stop-retailer.frontend.dashboard.sh - - sudo bash /tmp/delete-retailer.frontend.dashboard.sh - when: destroy - retailer.frontend.dashboard~service.application#docker.image::kubernetes@kubernetes.cluster: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: 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 }} 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 - retailer.frontend.dashboard~service.application#docker.image::compose@docker.engine->local.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 - retailer.frontend.dashboard~service.application#docker.image::compose@docker.engine->remote.machine: - derived_from: retailer.frontend.dashboard - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 }}' - retailer.frontend.terminal~service.application#docker.image::ansible@docker.engine->local.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: stop container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - state: absent - retailer.frontend.terminal~service.application#docker.image::ansible@docker.engine->remote.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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 }}' - retailer.frontend.terminal~service.application#docker.image::ansible@gcp.cloudrun: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: touch service - register: service - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.service.yaml' - - name: create service - ansible.builtin.copy: - dest: '{{ service.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - apiVersion: serving.knative.dev/v1 - kind: Service - metadata: - name: '{{ SELF.application_name }}' - labels: - cloud.googleapis.com/location: '{{ SELF.gcp_region }}' - annotations: - run.googleapis.com/ingress: all - spec: - template: - spec: - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - containerPort: '{{ SELF.application_port }}' - env: [] - - name: apply service - ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet - args: - executable: /bin/bash - - name: touch policy - register: policy - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.policy.yaml' - - name: fill policy - ansible.builtin.copy: - dest: '{{ policy.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - bindings: - - members: - - allUsers - role: roles/run.invoker - - name: apply policy - ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - - name: describe service - register: service_description - ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - retailer.frontend.terminal~service.application#docker.image::ansible@kubernetes.cluster: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: create deployment - kubernetes.core.k8s: - wait: true - definition: - 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 }}' - - name: create service - kubernetes.core.k8s: - definition: - 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 - 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 }}' - retailer.frontend.terminal~service.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.frontend.terminal~service.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.frontend.terminal~service.application#zip.archive::ansible@gcp.appengine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: enable GCP AppEngine - ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - register: app_create_command - failed_when: - - "'Created' not in app_create_command.stderr" - - "'already contains' not in app_create_command.stderr" - - name: create working directory - register: directory - ansible.builtin.tempfile: - state: directory - - name: extract deployment artifact in working directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ directory.path }}' - - name: create specification - ansible.builtin.copy: - dest: '{{ directory.path }}/app.yaml' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - instance_class: F1 - env_variables: {} - - name: create app - ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet - args: - executable: /bin/bash - - name: browse app - register: browse_app - ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ browse_app.stdout[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet - args: - executable: /bin/bash - retailer.frontend.terminal~software.application#apt.package::ansible@*->remote.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.frontend.terminal~software.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.frontend.terminal~software.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.frontend.terminal~service.application#docker.image::terraform@docker.engine->local.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: unix:///var/run/docker.sock - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.frontend.terminal~service.application#docker.image::terraform@docker.engine->remote.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 - ssh_opts: - - '-i' - - '{{ SELF.os_ssh_key_file }}' - - '-o' - - IdentitiesOnly=yes - - '-o' - - BatchMode=yes - - '-o' - - UserKnownHostsFile=/dev/null - - '-o' - - StrictHostKeyChecking=no - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.frontend.terminal~service.application#docker.image::terraform@gcp.cloudrun: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' - resource: - google_cloud_run_v2_service: - application: - - ingress: INGRESS_TRAFFIC_ALL - location: '{{ SELF.gcp_region }}' - name: '{{ SELF.application_name }}' - template: - - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - container_port: '{{ SELF.application_port }}' - env: [] - google_cloud_run_service_iam_binding: - application: - - location: '{{ SELF.gcp_region }}' - members: - - allUsers - role: roles/run.invoker - service: '{{ SELF.application_name }}' - retailer.frontend.terminal~service.application#docker.image::terraform@kubernetes.cluster: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - kubernetes: - source: hashicorp/kubernetes - version: 2.31.0 - required_version: '>= 0.14.0' - provider: - kubernetes: - - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} - client_key: ${file("{{ SELF.k8s_client_key_file }}")} - cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} - host: '{{ SELF.k8s_host }}' - resource: - kubernetes_deployment_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - selector: - - match_labels: - app: '{{ SELF.application_name }}' - template: - - metadata: - - labels: - app: '{{ SELF.application_name }}' - spec: - - container: - - env: [] - image: '{{ ".artifacts::docker_image::file" | eval }}' - name: '{{ SELF.application_name }}' - port: - - container_port: '{{ SELF.application_port }}' - kubernetes_service_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - port: - - name: '{{ SELF.application_protocol }}' - port: '{{ SELF.application_port }}' - target_port: '{{ SELF.application_port }}' - selector: - app: '{{ SELF.application_name }}' - type: ClusterIP - retailer.frontend.terminal~service.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.frontend.terminal - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.frontend.terminal {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.frontend.terminal -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.frontend.terminal.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.frontend.terminal.sh - - sudo bash /tmp/configure-retailer.frontend.terminal.sh - - sudo bash /tmp/start-retailer.frontend.terminal.sh - - inline: - - sudo bash /tmp/stop-retailer.frontend.terminal.sh - - sudo bash /tmp/delete-retailer.frontend.terminal.sh - when: destroy - retailer.frontend.terminal~service.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.frontend.terminal - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.frontend.terminal {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.frontend.terminal -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.frontend.terminal.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.frontend.terminal.sh - - sudo bash /tmp/configure-retailer.frontend.terminal.sh - - sudo bash /tmp/start-retailer.frontend.terminal.sh - - inline: - - sudo bash /tmp/stop-retailer.frontend.terminal.sh - - sudo bash /tmp/delete-retailer.frontend.terminal.sh - when: destroy - retailer.frontend.terminal~service.application#zip.archive::terraform@gcp.appengine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' - resource: - google_app_engine_standard_app_version: - app: - - delete_service_on_destroy: true - deployment: - - zip: - - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} - entrypoint: - - shell: '{{ SELF._management_start }}' - env_variables: {} - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - service_account: ${google_service_account.custom_service_account.email} - version_id: v1 - google_project_iam_member: - gae_api: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/compute.networkUser - storage_viewer: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/storage.objectViewer - google_service_account: - custom_service_account: - - account_id: '{{ SELF.application_name }}-account' - display_name: Custom Service Account - google_storage_bucket: - bucket: - - location: EU - name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' - google_storage_bucket_object: - object: - - bucket: ${google_storage_bucket.bucket.name} - name: object.zip - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - retailer.frontend.terminal~software.application#apt.archive::terraform@*->remote.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.frontend.terminal {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-retailer.frontend.terminal.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.frontend.terminal.sh - - sudo bash /tmp/configure-retailer.frontend.terminal.sh - - sudo bash /tmp/start-retailer.frontend.terminal.sh - - inline: - - sudo bash /tmp/stop-retailer.frontend.terminal.sh - - sudo bash /tmp/delete-retailer.frontend.terminal.sh - when: destroy - retailer.frontend.terminal~software.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.frontend.terminal - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.frontend.terminal {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.frontend.terminal -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.frontend.terminal.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.frontend.terminal.sh - - sudo bash /tmp/configure-retailer.frontend.terminal.sh - - sudo bash /tmp/start-retailer.frontend.terminal.sh - - inline: - - sudo bash /tmp/stop-retailer.frontend.terminal.sh - - sudo bash /tmp/delete-retailer.frontend.terminal.sh - when: destroy - retailer.frontend.terminal~software.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.frontend.terminal - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.frontend.terminal {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.frontend.terminal -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.frontend.terminal.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.frontend.terminal.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.frontend.terminal.sh - - sudo bash /tmp/configure-retailer.frontend.terminal.sh - - sudo bash /tmp/start-retailer.frontend.terminal.sh - - inline: - - sudo bash /tmp/stop-retailer.frontend.terminal.sh - - sudo bash /tmp/delete-retailer.frontend.terminal.sh - when: destroy - retailer.frontend.terminal~service.application#docker.image::kubernetes@kubernetes.cluster: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: 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 }} 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 - retailer.frontend.terminal~service.application#docker.image::compose@docker.engine->local.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 - retailer.frontend.terminal~service.application#docker.image::compose@docker.engine->remote.machine: - derived_from: retailer.frontend.terminal - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 }}' - retailer.service.gateway~service.application#docker.image::ansible@docker.engine->local.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: stop container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - state: absent - retailer.service.gateway~service.application#docker.image::ansible@docker.engine->remote.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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 }}' - retailer.service.gateway~service.application#docker.image::ansible@gcp.cloudrun: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: touch service - register: service - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.service.yaml' - - name: create service - ansible.builtin.copy: - dest: '{{ service.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - apiVersion: serving.knative.dev/v1 - kind: Service - metadata: - name: '{{ SELF.application_name }}' - labels: - cloud.googleapis.com/location: '{{ SELF.gcp_region }}' - annotations: - run.googleapis.com/ingress: all - spec: - template: - spec: - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - containerPort: '{{ SELF.application_port }}' - env: [] - - name: apply service - ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet - args: - executable: /bin/bash - - name: touch policy - register: policy - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.policy.yaml' - - name: fill policy - ansible.builtin.copy: - dest: '{{ policy.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - bindings: - - members: - - allUsers - role: roles/run.invoker - - name: apply policy - ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - - name: describe service - register: service_description - ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - retailer.service.gateway~service.application#docker.image::ansible@kubernetes.cluster: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: create deployment - kubernetes.core.k8s: - wait: true - definition: - 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 }}' - - name: create service - kubernetes.core.k8s: - definition: - 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 - 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 }}' - retailer.service.gateway~service.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.gateway~service.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.gateway~service.application#zip.archive::ansible@gcp.appengine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: enable GCP AppEngine - ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - register: app_create_command - failed_when: - - "'Created' not in app_create_command.stderr" - - "'already contains' not in app_create_command.stderr" - - name: create working directory - register: directory - ansible.builtin.tempfile: - state: directory - - name: extract deployment artifact in working directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ directory.path }}' - - name: create specification - ansible.builtin.copy: - dest: '{{ directory.path }}/app.yaml' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - instance_class: F1 - env_variables: {} - - name: create app - ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet - args: - executable: /bin/bash - - name: browse app - register: browse_app - ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ browse_app.stdout[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet - args: - executable: /bin/bash - retailer.service.gateway~software.application#apt.package::ansible@*->remote.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.gateway~software.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.gateway~software.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.gateway~service.application#docker.image::terraform@docker.engine->local.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: unix:///var/run/docker.sock - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.gateway~service.application#docker.image::terraform@docker.engine->remote.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 - ssh_opts: - - '-i' - - '{{ SELF.os_ssh_key_file }}' - - '-o' - - IdentitiesOnly=yes - - '-o' - - BatchMode=yes - - '-o' - - UserKnownHostsFile=/dev/null - - '-o' - - StrictHostKeyChecking=no - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.gateway~service.application#docker.image::terraform@gcp.cloudrun: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' - resource: - google_cloud_run_v2_service: - application: - - ingress: INGRESS_TRAFFIC_ALL - location: '{{ SELF.gcp_region }}' - name: '{{ SELF.application_name }}' - template: - - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - container_port: '{{ SELF.application_port }}' - env: [] - google_cloud_run_service_iam_binding: - application: - - location: '{{ SELF.gcp_region }}' - members: - - allUsers - role: roles/run.invoker - service: '{{ SELF.application_name }}' - retailer.service.gateway~service.application#docker.image::terraform@kubernetes.cluster: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - kubernetes: - source: hashicorp/kubernetes - version: 2.31.0 - required_version: '>= 0.14.0' - provider: - kubernetes: - - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} - client_key: ${file("{{ SELF.k8s_client_key_file }}")} - cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} - host: '{{ SELF.k8s_host }}' - resource: - kubernetes_deployment_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - selector: - - match_labels: - app: '{{ SELF.application_name }}' - template: - - metadata: - - labels: - app: '{{ SELF.application_name }}' - spec: - - container: - - env: [] - image: '{{ ".artifacts::docker_image::file" | eval }}' - name: '{{ SELF.application_name }}' - port: - - container_port: '{{ SELF.application_port }}' - kubernetes_service_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - port: - - name: '{{ SELF.application_protocol }}' - port: '{{ SELF.application_port }}' - target_port: '{{ SELF.application_port }}' - selector: - app: '{{ SELF.application_name }}' - type: ClusterIP - retailer.service.gateway~service.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.gateway - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.gateway {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.gateway -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.gateway.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.gateway.sh - - sudo bash /tmp/configure-retailer.service.gateway.sh - - sudo bash /tmp/start-retailer.service.gateway.sh - - inline: - - sudo bash /tmp/stop-retailer.service.gateway.sh - - sudo bash /tmp/delete-retailer.service.gateway.sh - when: destroy - retailer.service.gateway~service.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.gateway - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.gateway {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.gateway -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.gateway.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.gateway.sh - - sudo bash /tmp/configure-retailer.service.gateway.sh - - sudo bash /tmp/start-retailer.service.gateway.sh - - inline: - - sudo bash /tmp/stop-retailer.service.gateway.sh - - sudo bash /tmp/delete-retailer.service.gateway.sh - when: destroy - retailer.service.gateway~service.application#zip.archive::terraform@gcp.appengine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' - resource: - google_app_engine_standard_app_version: - app: - - delete_service_on_destroy: true - deployment: - - zip: - - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} - entrypoint: - - shell: '{{ SELF._management_start }}' - env_variables: {} - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - service_account: ${google_service_account.custom_service_account.email} - version_id: v1 - google_project_iam_member: - gae_api: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/compute.networkUser - storage_viewer: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/storage.objectViewer - google_service_account: - custom_service_account: - - account_id: '{{ SELF.application_name }}-account' - display_name: Custom Service Account - google_storage_bucket: - bucket: - - location: EU - name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' - google_storage_bucket_object: - object: - - bucket: ${google_storage_bucket.bucket.name} - name: object.zip - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - retailer.service.gateway~software.application#apt.archive::terraform@*->remote.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.gateway {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-retailer.service.gateway.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.gateway.sh - - sudo bash /tmp/configure-retailer.service.gateway.sh - - sudo bash /tmp/start-retailer.service.gateway.sh - - inline: - - sudo bash /tmp/stop-retailer.service.gateway.sh - - sudo bash /tmp/delete-retailer.service.gateway.sh - when: destroy - retailer.service.gateway~software.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.gateway - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.gateway {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.gateway -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.gateway.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.gateway.sh - - sudo bash /tmp/configure-retailer.service.gateway.sh - - sudo bash /tmp/start-retailer.service.gateway.sh - - inline: - - sudo bash /tmp/stop-retailer.service.gateway.sh - - sudo bash /tmp/delete-retailer.service.gateway.sh - when: destroy - retailer.service.gateway~software.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.gateway - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.gateway {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.gateway -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.gateway.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.gateway.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.gateway.sh - - sudo bash /tmp/configure-retailer.service.gateway.sh - - sudo bash /tmp/start-retailer.service.gateway.sh - - inline: - - sudo bash /tmp/stop-retailer.service.gateway.sh - - sudo bash /tmp/delete-retailer.service.gateway.sh - when: destroy - retailer.service.gateway~service.application#docker.image::kubernetes@kubernetes.cluster: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: 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 }} 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 - retailer.service.gateway~service.application#docker.image::compose@docker.engine->local.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 - retailer.service.gateway~service.application#docker.image::compose@docker.engine->remote.machine: - derived_from: retailer.service.gateway - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 }}' - retailer.service.core~service.application#docker.image::ansible@docker.engine->local.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: stop container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - state: absent - retailer.service.core~service.application#docker.image::ansible@docker.engine->remote.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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 }}' - retailer.service.core~service.application#docker.image::ansible@gcp.cloudrun: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: touch service - register: service - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.service.yaml' - - name: create service - ansible.builtin.copy: - dest: '{{ service.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - apiVersion: serving.knative.dev/v1 - kind: Service - metadata: - name: '{{ SELF.application_name }}' - labels: - cloud.googleapis.com/location: '{{ SELF.gcp_region }}' - annotations: - run.googleapis.com/ingress: all - spec: - template: - spec: - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - containerPort: '{{ SELF.application_port }}' - env: [] - - name: apply service - ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet - args: - executable: /bin/bash - - name: touch policy - register: policy - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.policy.yaml' - - name: fill policy - ansible.builtin.copy: - dest: '{{ policy.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - bindings: - - members: - - allUsers - role: roles/run.invoker - - name: apply policy - ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - - name: describe service - register: service_description - ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - retailer.service.core~service.application#docker.image::ansible@kubernetes.cluster: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: create deployment - kubernetes.core.k8s: - wait: true - definition: - 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 }}' - - name: create service - kubernetes.core.k8s: - definition: - 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 - 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 }}' - retailer.service.core~service.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.core~service.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.core~service.application#zip.archive::ansible@gcp.appengine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: enable GCP AppEngine - ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - register: app_create_command - failed_when: - - "'Created' not in app_create_command.stderr" - - "'already contains' not in app_create_command.stderr" - - name: create working directory - register: directory - ansible.builtin.tempfile: - state: directory - - name: extract deployment artifact in working directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ directory.path }}' - - name: create specification - ansible.builtin.copy: - dest: '{{ directory.path }}/app.yaml' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - instance_class: F1 - env_variables: {} - - name: create app - ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet - args: - executable: /bin/bash - - name: browse app - register: browse_app - ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ browse_app.stdout[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet - args: - executable: /bin/bash - retailer.service.core~software.application#apt.package::ansible@*->remote.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.core~software.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.core~software.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.core~service.application#docker.image::terraform@docker.engine->local.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: unix:///var/run/docker.sock - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.core~service.application#docker.image::terraform@docker.engine->remote.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 - ssh_opts: - - '-i' - - '{{ SELF.os_ssh_key_file }}' - - '-o' - - IdentitiesOnly=yes - - '-o' - - BatchMode=yes - - '-o' - - UserKnownHostsFile=/dev/null - - '-o' - - StrictHostKeyChecking=no - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.core~service.application#docker.image::terraform@gcp.cloudrun: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' - resource: - google_cloud_run_v2_service: - application: - - ingress: INGRESS_TRAFFIC_ALL - location: '{{ SELF.gcp_region }}' - name: '{{ SELF.application_name }}' - template: - - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - container_port: '{{ SELF.application_port }}' - env: [] - google_cloud_run_service_iam_binding: - application: - - location: '{{ SELF.gcp_region }}' - members: - - allUsers - role: roles/run.invoker - service: '{{ SELF.application_name }}' - retailer.service.core~service.application#docker.image::terraform@kubernetes.cluster: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - kubernetes: - source: hashicorp/kubernetes - version: 2.31.0 - required_version: '>= 0.14.0' - provider: - kubernetes: - - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} - client_key: ${file("{{ SELF.k8s_client_key_file }}")} - cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} - host: '{{ SELF.k8s_host }}' - resource: - kubernetes_deployment_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - selector: - - match_labels: - app: '{{ SELF.application_name }}' - template: - - metadata: - - labels: - app: '{{ SELF.application_name }}' - spec: - - container: - - env: [] - image: '{{ ".artifacts::docker_image::file" | eval }}' - name: '{{ SELF.application_name }}' - port: - - container_port: '{{ SELF.application_port }}' - kubernetes_service_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - port: - - name: '{{ SELF.application_protocol }}' - port: '{{ SELF.application_port }}' - target_port: '{{ SELF.application_port }}' - selector: - app: '{{ SELF.application_name }}' - type: ClusterIP - retailer.service.core~service.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.core - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.core {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.core -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.core.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.core.sh - - sudo bash /tmp/configure-retailer.service.core.sh - - sudo bash /tmp/start-retailer.service.core.sh - - inline: - - sudo bash /tmp/stop-retailer.service.core.sh - - sudo bash /tmp/delete-retailer.service.core.sh - when: destroy - retailer.service.core~service.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.core - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.core {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.core -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.core.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.core.sh - - sudo bash /tmp/configure-retailer.service.core.sh - - sudo bash /tmp/start-retailer.service.core.sh - - inline: - - sudo bash /tmp/stop-retailer.service.core.sh - - sudo bash /tmp/delete-retailer.service.core.sh - when: destroy - retailer.service.core~service.application#zip.archive::terraform@gcp.appengine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' - resource: - google_app_engine_standard_app_version: - app: - - delete_service_on_destroy: true - deployment: - - zip: - - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} - entrypoint: - - shell: '{{ SELF._management_start }}' - env_variables: {} - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - service_account: ${google_service_account.custom_service_account.email} - version_id: v1 - google_project_iam_member: - gae_api: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/compute.networkUser - storage_viewer: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/storage.objectViewer - google_service_account: - custom_service_account: - - account_id: '{{ SELF.application_name }}-account' - display_name: Custom Service Account - google_storage_bucket: - bucket: - - location: EU - name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' - google_storage_bucket_object: - object: - - bucket: ${google_storage_bucket.bucket.name} - name: object.zip - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - retailer.service.core~software.application#apt.archive::terraform@*->remote.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.core {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-retailer.service.core.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.core.sh - - sudo bash /tmp/configure-retailer.service.core.sh - - sudo bash /tmp/start-retailer.service.core.sh - - inline: - - sudo bash /tmp/stop-retailer.service.core.sh - - sudo bash /tmp/delete-retailer.service.core.sh - when: destroy - retailer.service.core~software.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.core - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.core {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.core -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.core.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.core.sh - - sudo bash /tmp/configure-retailer.service.core.sh - - sudo bash /tmp/start-retailer.service.core.sh - - inline: - - sudo bash /tmp/stop-retailer.service.core.sh - - sudo bash /tmp/delete-retailer.service.core.sh - when: destroy - retailer.service.core~software.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.core - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.core {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.core -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.core.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.core.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.core.sh - - sudo bash /tmp/configure-retailer.service.core.sh - - sudo bash /tmp/start-retailer.service.core.sh - - inline: - - sudo bash /tmp/stop-retailer.service.core.sh - - sudo bash /tmp/delete-retailer.service.core.sh - when: destroy - retailer.service.core~service.application#docker.image::kubernetes@kubernetes.cluster: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: 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 }} 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 - retailer.service.core~service.application#docker.image::compose@docker.engine->local.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 - retailer.service.core~service.application#docker.image::compose@docker.engine->remote.machine: - derived_from: retailer.service.core - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 }}' - retailer.service.jobs~service.application#docker.image::ansible@docker.engine->local.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: stop container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - state: absent - retailer.service.jobs~service.application#docker.image::ansible@docker.engine->remote.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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 }}' - retailer.service.jobs~service.application#docker.image::ansible@gcp.cloudrun: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: touch service - register: service - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.service.yaml' - - name: create service - ansible.builtin.copy: - dest: '{{ service.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - apiVersion: serving.knative.dev/v1 - kind: Service - metadata: - name: '{{ SELF.application_name }}' - labels: - cloud.googleapis.com/location: '{{ SELF.gcp_region }}' - annotations: - run.googleapis.com/ingress: all - spec: - template: - spec: - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - containerPort: '{{ SELF.application_port }}' - env: [] - - name: apply service - ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet - args: - executable: /bin/bash - - name: touch policy - register: policy - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.policy.yaml' - - name: fill policy - ansible.builtin.copy: - dest: '{{ policy.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - bindings: - - members: - - allUsers - role: roles/run.invoker - - name: apply policy - ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - - name: describe service - register: service_description - ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - retailer.service.jobs~service.application#docker.image::ansible@kubernetes.cluster: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: create deployment - kubernetes.core.k8s: - wait: true - definition: - 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 }}' - - name: create service - kubernetes.core.k8s: - definition: - 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 - 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 }}' - retailer.service.jobs~service.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.jobs~service.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.jobs~service.application#zip.archive::ansible@gcp.appengine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: enable GCP AppEngine - ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - register: app_create_command - failed_when: - - "'Created' not in app_create_command.stderr" - - "'already contains' not in app_create_command.stderr" - - name: create working directory - register: directory - ansible.builtin.tempfile: - state: directory - - name: extract deployment artifact in working directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ directory.path }}' - - name: create specification - ansible.builtin.copy: - dest: '{{ directory.path }}/app.yaml' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - instance_class: F1 - env_variables: {} - - name: create app - ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet - args: - executable: /bin/bash - - name: browse app - register: browse_app - ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ browse_app.stdout[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet - args: - executable: /bin/bash - retailer.service.jobs~software.application#apt.package::ansible@*->remote.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.jobs~software.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.jobs~software.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.jobs~service.application#docker.image::terraform@docker.engine->local.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: unix:///var/run/docker.sock - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.jobs~service.application#docker.image::terraform@docker.engine->remote.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 - ssh_opts: - - '-i' - - '{{ SELF.os_ssh_key_file }}' - - '-o' - - IdentitiesOnly=yes - - '-o' - - BatchMode=yes - - '-o' - - UserKnownHostsFile=/dev/null - - '-o' - - StrictHostKeyChecking=no - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.jobs~service.application#docker.image::terraform@gcp.cloudrun: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' - resource: - google_cloud_run_v2_service: - application: - - ingress: INGRESS_TRAFFIC_ALL - location: '{{ SELF.gcp_region }}' - name: '{{ SELF.application_name }}' - template: - - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - container_port: '{{ SELF.application_port }}' - env: [] - google_cloud_run_service_iam_binding: - application: - - location: '{{ SELF.gcp_region }}' - members: - - allUsers - role: roles/run.invoker - service: '{{ SELF.application_name }}' - retailer.service.jobs~service.application#docker.image::terraform@kubernetes.cluster: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - kubernetes: - source: hashicorp/kubernetes - version: 2.31.0 - required_version: '>= 0.14.0' - provider: - kubernetes: - - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} - client_key: ${file("{{ SELF.k8s_client_key_file }}")} - cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} - host: '{{ SELF.k8s_host }}' - resource: - kubernetes_deployment_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - selector: - - match_labels: - app: '{{ SELF.application_name }}' - template: - - metadata: - - labels: - app: '{{ SELF.application_name }}' - spec: - - container: - - env: [] - image: '{{ ".artifacts::docker_image::file" | eval }}' - name: '{{ SELF.application_name }}' - port: - - container_port: '{{ SELF.application_port }}' - kubernetes_service_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - port: - - name: '{{ SELF.application_protocol }}' - port: '{{ SELF.application_port }}' - target_port: '{{ SELF.application_port }}' - selector: - app: '{{ SELF.application_name }}' - type: ClusterIP - retailer.service.jobs~service.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.jobs - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.jobs {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.jobs -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.jobs.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.jobs.sh - - sudo bash /tmp/configure-retailer.service.jobs.sh - - sudo bash /tmp/start-retailer.service.jobs.sh - - inline: - - sudo bash /tmp/stop-retailer.service.jobs.sh - - sudo bash /tmp/delete-retailer.service.jobs.sh - when: destroy - retailer.service.jobs~service.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.jobs - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.jobs {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.jobs -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.jobs.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.jobs.sh - - sudo bash /tmp/configure-retailer.service.jobs.sh - - sudo bash /tmp/start-retailer.service.jobs.sh - - inline: - - sudo bash /tmp/stop-retailer.service.jobs.sh - - sudo bash /tmp/delete-retailer.service.jobs.sh - when: destroy - retailer.service.jobs~service.application#zip.archive::terraform@gcp.appengine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' - resource: - google_app_engine_standard_app_version: - app: - - delete_service_on_destroy: true - deployment: - - zip: - - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} - entrypoint: - - shell: '{{ SELF._management_start }}' - env_variables: {} - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - service_account: ${google_service_account.custom_service_account.email} - version_id: v1 - google_project_iam_member: - gae_api: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/compute.networkUser - storage_viewer: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/storage.objectViewer - google_service_account: - custom_service_account: - - account_id: '{{ SELF.application_name }}-account' - display_name: Custom Service Account - google_storage_bucket: - bucket: - - location: EU - name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' - google_storage_bucket_object: - object: - - bucket: ${google_storage_bucket.bucket.name} - name: object.zip - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - retailer.service.jobs~software.application#apt.archive::terraform@*->remote.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.jobs {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-retailer.service.jobs.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.jobs.sh - - sudo bash /tmp/configure-retailer.service.jobs.sh - - sudo bash /tmp/start-retailer.service.jobs.sh - - inline: - - sudo bash /tmp/stop-retailer.service.jobs.sh - - sudo bash /tmp/delete-retailer.service.jobs.sh - when: destroy - retailer.service.jobs~software.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.jobs - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.jobs {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.jobs -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.jobs.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.jobs.sh - - sudo bash /tmp/configure-retailer.service.jobs.sh - - sudo bash /tmp/start-retailer.service.jobs.sh - - inline: - - sudo bash /tmp/stop-retailer.service.jobs.sh - - sudo bash /tmp/delete-retailer.service.jobs.sh - when: destroy - retailer.service.jobs~software.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.jobs - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.jobs {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.jobs -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.jobs.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.jobs.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.jobs.sh - - sudo bash /tmp/configure-retailer.service.jobs.sh - - sudo bash /tmp/start-retailer.service.jobs.sh - - inline: - - sudo bash /tmp/stop-retailer.service.jobs.sh - - sudo bash /tmp/delete-retailer.service.jobs.sh - when: destroy - retailer.service.jobs~service.application#docker.image::kubernetes@kubernetes.cluster: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: 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 }} 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 - retailer.service.jobs~service.application#docker.image::compose@docker.engine->local.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 - retailer.service.jobs~service.application#docker.image::compose@docker.engine->remote.machine: - derived_from: retailer.service.jobs - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 }}' - retailer.service.stores~service.application#docker.image::ansible@docker.engine->local.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: stop container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - state: absent - retailer.service.stores~service.application#docker.image::ansible@docker.engine->remote.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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 }}' - retailer.service.stores~service.application#docker.image::ansible@gcp.cloudrun: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: touch service - register: service - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.service.yaml' - - name: create service - ansible.builtin.copy: - dest: '{{ service.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - apiVersion: serving.knative.dev/v1 - kind: Service - metadata: - name: '{{ SELF.application_name }}' - labels: - cloud.googleapis.com/location: '{{ SELF.gcp_region }}' - annotations: - run.googleapis.com/ingress: all - spec: - template: - spec: - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - containerPort: '{{ SELF.application_port }}' - env: [] - - name: apply service - ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet - args: - executable: /bin/bash - - name: touch policy - register: policy - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.policy.yaml' - - name: fill policy - ansible.builtin.copy: - dest: '{{ policy.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - bindings: - - members: - - allUsers - role: roles/run.invoker - - name: apply policy - ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - - name: describe service - register: service_description - ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - retailer.service.stores~service.application#docker.image::ansible@kubernetes.cluster: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: create deployment - kubernetes.core.k8s: - wait: true - definition: - 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 }}' - - name: create service - kubernetes.core.k8s: - definition: - 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 - 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 }}' - retailer.service.stores~service.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.stores~service.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.stores~service.application#zip.archive::ansible@gcp.appengine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: enable GCP AppEngine - ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - register: app_create_command - failed_when: - - "'Created' not in app_create_command.stderr" - - "'already contains' not in app_create_command.stderr" - - name: create working directory - register: directory - ansible.builtin.tempfile: - state: directory - - name: extract deployment artifact in working directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ directory.path }}' - - name: create specification - ansible.builtin.copy: - dest: '{{ directory.path }}/app.yaml' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - instance_class: F1 - env_variables: {} - - name: create app - ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet - args: - executable: /bin/bash - - name: browse app - register: browse_app - ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ browse_app.stdout[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet - args: - executable: /bin/bash - retailer.service.stores~software.application#apt.package::ansible@*->remote.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.stores~software.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.stores~software.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.stores~service.application#docker.image::terraform@docker.engine->local.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: unix:///var/run/docker.sock - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.stores~service.application#docker.image::terraform@docker.engine->remote.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 - ssh_opts: - - '-i' - - '{{ SELF.os_ssh_key_file }}' - - '-o' - - IdentitiesOnly=yes - - '-o' - - BatchMode=yes - - '-o' - - UserKnownHostsFile=/dev/null - - '-o' - - StrictHostKeyChecking=no - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.stores~service.application#docker.image::terraform@gcp.cloudrun: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' - resource: - google_cloud_run_v2_service: - application: - - ingress: INGRESS_TRAFFIC_ALL - location: '{{ SELF.gcp_region }}' - name: '{{ SELF.application_name }}' - template: - - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - container_port: '{{ SELF.application_port }}' - env: [] - google_cloud_run_service_iam_binding: - application: - - location: '{{ SELF.gcp_region }}' - members: - - allUsers - role: roles/run.invoker - service: '{{ SELF.application_name }}' - retailer.service.stores~service.application#docker.image::terraform@kubernetes.cluster: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - kubernetes: - source: hashicorp/kubernetes - version: 2.31.0 - required_version: '>= 0.14.0' - provider: - kubernetes: - - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} - client_key: ${file("{{ SELF.k8s_client_key_file }}")} - cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} - host: '{{ SELF.k8s_host }}' - resource: - kubernetes_deployment_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - selector: - - match_labels: - app: '{{ SELF.application_name }}' - template: - - metadata: - - labels: - app: '{{ SELF.application_name }}' - spec: - - container: - - env: [] - image: '{{ ".artifacts::docker_image::file" | eval }}' - name: '{{ SELF.application_name }}' - port: - - container_port: '{{ SELF.application_port }}' - kubernetes_service_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - port: - - name: '{{ SELF.application_protocol }}' - port: '{{ SELF.application_port }}' - target_port: '{{ SELF.application_port }}' - selector: - app: '{{ SELF.application_name }}' - type: ClusterIP - retailer.service.stores~service.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.stores - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.stores {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.stores -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.stores.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.stores.sh - - sudo bash /tmp/configure-retailer.service.stores.sh - - sudo bash /tmp/start-retailer.service.stores.sh - - inline: - - sudo bash /tmp/stop-retailer.service.stores.sh - - sudo bash /tmp/delete-retailer.service.stores.sh - when: destroy - retailer.service.stores~service.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.stores - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.stores {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.stores -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.stores.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.stores.sh - - sudo bash /tmp/configure-retailer.service.stores.sh - - sudo bash /tmp/start-retailer.service.stores.sh - - inline: - - sudo bash /tmp/stop-retailer.service.stores.sh - - sudo bash /tmp/delete-retailer.service.stores.sh - when: destroy - retailer.service.stores~service.application#zip.archive::terraform@gcp.appengine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' - resource: - google_app_engine_standard_app_version: - app: - - delete_service_on_destroy: true - deployment: - - zip: - - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} - entrypoint: - - shell: '{{ SELF._management_start }}' - env_variables: {} - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - service_account: ${google_service_account.custom_service_account.email} - version_id: v1 - google_project_iam_member: - gae_api: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/compute.networkUser - storage_viewer: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/storage.objectViewer - google_service_account: - custom_service_account: - - account_id: '{{ SELF.application_name }}-account' - display_name: Custom Service Account - google_storage_bucket: - bucket: - - location: EU - name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' - google_storage_bucket_object: - object: - - bucket: ${google_storage_bucket.bucket.name} - name: object.zip - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - retailer.service.stores~software.application#apt.archive::terraform@*->remote.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.stores {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-retailer.service.stores.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.stores.sh - - sudo bash /tmp/configure-retailer.service.stores.sh - - sudo bash /tmp/start-retailer.service.stores.sh - - inline: - - sudo bash /tmp/stop-retailer.service.stores.sh - - sudo bash /tmp/delete-retailer.service.stores.sh - when: destroy - retailer.service.stores~software.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.stores - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.stores {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.stores -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.stores.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.stores.sh - - sudo bash /tmp/configure-retailer.service.stores.sh - - sudo bash /tmp/start-retailer.service.stores.sh - - inline: - - sudo bash /tmp/stop-retailer.service.stores.sh - - sudo bash /tmp/delete-retailer.service.stores.sh - when: destroy - retailer.service.stores~software.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.stores - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.stores {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.stores -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.stores.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.stores.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.stores.sh - - sudo bash /tmp/configure-retailer.service.stores.sh - - sudo bash /tmp/start-retailer.service.stores.sh - - inline: - - sudo bash /tmp/stop-retailer.service.stores.sh - - sudo bash /tmp/delete-retailer.service.stores.sh - when: destroy - retailer.service.stores~service.application#docker.image::kubernetes@kubernetes.cluster: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: 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 }} 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 - retailer.service.stores~service.application#docker.image::compose@docker.engine->local.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 - retailer.service.stores~service.application#docker.image::compose@docker.engine->remote.machine: - derived_from: retailer.service.stores - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 }}' - retailer.service.products~service.application#docker.image::ansible@docker.engine->local.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: stop container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - state: absent - retailer.service.products~service.application#docker.image::ansible@docker.engine->remote.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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 }}' - retailer.service.products~service.application#docker.image::ansible@gcp.cloudrun: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: touch service - register: service - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.service.yaml' - - name: create service - ansible.builtin.copy: - dest: '{{ service.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - apiVersion: serving.knative.dev/v1 - kind: Service - metadata: - name: '{{ SELF.application_name }}' - labels: - cloud.googleapis.com/location: '{{ SELF.gcp_region }}' - annotations: - run.googleapis.com/ingress: all - spec: - template: - spec: - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - containerPort: '{{ SELF.application_port }}' - env: [] - - name: apply service - ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet - args: - executable: /bin/bash - - name: touch policy - register: policy - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.policy.yaml' - - name: fill policy - ansible.builtin.copy: - dest: '{{ policy.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - bindings: - - members: - - allUsers - role: roles/run.invoker - - name: apply policy - ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - - name: describe service - register: service_description - ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - retailer.service.products~service.application#docker.image::ansible@kubernetes.cluster: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: create deployment - kubernetes.core.k8s: - wait: true - definition: - 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 }}' - - name: create service - kubernetes.core.k8s: - definition: - 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 - 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 }}' - retailer.service.products~service.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.products~service.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.products~service.application#zip.archive::ansible@gcp.appengine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: enable GCP AppEngine - ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - register: app_create_command - failed_when: - - "'Created' not in app_create_command.stderr" - - "'already contains' not in app_create_command.stderr" - - name: create working directory - register: directory - ansible.builtin.tempfile: - state: directory - - name: extract deployment artifact in working directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ directory.path }}' - - name: create specification - ansible.builtin.copy: - dest: '{{ directory.path }}/app.yaml' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - instance_class: F1 - env_variables: {} - - name: create app - ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet - args: - executable: /bin/bash - - name: browse app - register: browse_app - ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ browse_app.stdout[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet - args: - executable: /bin/bash - retailer.service.products~software.application#apt.package::ansible@*->remote.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.products~software.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.products~software.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.products~service.application#docker.image::terraform@docker.engine->local.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: unix:///var/run/docker.sock - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.products~service.application#docker.image::terraform@docker.engine->remote.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 - ssh_opts: - - '-i' - - '{{ SELF.os_ssh_key_file }}' - - '-o' - - IdentitiesOnly=yes - - '-o' - - BatchMode=yes - - '-o' - - UserKnownHostsFile=/dev/null - - '-o' - - StrictHostKeyChecking=no - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.products~service.application#docker.image::terraform@gcp.cloudrun: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' - resource: - google_cloud_run_v2_service: - application: - - ingress: INGRESS_TRAFFIC_ALL - location: '{{ SELF.gcp_region }}' - name: '{{ SELF.application_name }}' - template: - - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - container_port: '{{ SELF.application_port }}' - env: [] - google_cloud_run_service_iam_binding: - application: - - location: '{{ SELF.gcp_region }}' - members: - - allUsers - role: roles/run.invoker - service: '{{ SELF.application_name }}' - retailer.service.products~service.application#docker.image::terraform@kubernetes.cluster: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - kubernetes: - source: hashicorp/kubernetes - version: 2.31.0 - required_version: '>= 0.14.0' - provider: - kubernetes: - - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} - client_key: ${file("{{ SELF.k8s_client_key_file }}")} - cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} - host: '{{ SELF.k8s_host }}' - resource: - kubernetes_deployment_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - selector: - - match_labels: - app: '{{ SELF.application_name }}' - template: - - metadata: - - labels: - app: '{{ SELF.application_name }}' - spec: - - container: - - env: [] - image: '{{ ".artifacts::docker_image::file" | eval }}' - name: '{{ SELF.application_name }}' - port: - - container_port: '{{ SELF.application_port }}' - kubernetes_service_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - port: - - name: '{{ SELF.application_protocol }}' - port: '{{ SELF.application_port }}' - target_port: '{{ SELF.application_port }}' - selector: - app: '{{ SELF.application_name }}' - type: ClusterIP - retailer.service.products~service.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.products - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.products {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.products -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.products.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.products.sh - - sudo bash /tmp/configure-retailer.service.products.sh - - sudo bash /tmp/start-retailer.service.products.sh - - inline: - - sudo bash /tmp/stop-retailer.service.products.sh - - sudo bash /tmp/delete-retailer.service.products.sh - when: destroy - retailer.service.products~service.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.products - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.products {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.products -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.products.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.products.sh - - sudo bash /tmp/configure-retailer.service.products.sh - - sudo bash /tmp/start-retailer.service.products.sh - - inline: - - sudo bash /tmp/stop-retailer.service.products.sh - - sudo bash /tmp/delete-retailer.service.products.sh - when: destroy - retailer.service.products~service.application#zip.archive::terraform@gcp.appengine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' - resource: - google_app_engine_standard_app_version: - app: - - delete_service_on_destroy: true - deployment: - - zip: - - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} - entrypoint: - - shell: '{{ SELF._management_start }}' - env_variables: {} - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - service_account: ${google_service_account.custom_service_account.email} - version_id: v1 - google_project_iam_member: - gae_api: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/compute.networkUser - storage_viewer: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/storage.objectViewer - google_service_account: - custom_service_account: - - account_id: '{{ SELF.application_name }}-account' - display_name: Custom Service Account - google_storage_bucket: - bucket: - - location: EU - name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' - google_storage_bucket_object: - object: - - bucket: ${google_storage_bucket.bucket.name} - name: object.zip - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - retailer.service.products~software.application#apt.archive::terraform@*->remote.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.products {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-retailer.service.products.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.products.sh - - sudo bash /tmp/configure-retailer.service.products.sh - - sudo bash /tmp/start-retailer.service.products.sh - - inline: - - sudo bash /tmp/stop-retailer.service.products.sh - - sudo bash /tmp/delete-retailer.service.products.sh - when: destroy - retailer.service.products~software.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.products - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.products {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.products -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.products.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.products.sh - - sudo bash /tmp/configure-retailer.service.products.sh - - sudo bash /tmp/start-retailer.service.products.sh - - inline: - - sudo bash /tmp/stop-retailer.service.products.sh - - sudo bash /tmp/delete-retailer.service.products.sh - when: destroy - retailer.service.products~software.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.products - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.products {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.products -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.products.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.products.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.products.sh - - sudo bash /tmp/configure-retailer.service.products.sh - - sudo bash /tmp/start-retailer.service.products.sh - - inline: - - sudo bash /tmp/stop-retailer.service.products.sh - - sudo bash /tmp/delete-retailer.service.products.sh - when: destroy - retailer.service.products~service.application#docker.image::kubernetes@kubernetes.cluster: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: 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 }} 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 - retailer.service.products~service.application#docker.image::compose@docker.engine->local.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 - retailer.service.products~service.application#docker.image::compose@docker.engine->remote.machine: - derived_from: retailer.service.products - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 }}' - retailer.service.stocks~service.application#docker.image::ansible@docker.engine->local.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: stop container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - state: absent - retailer.service.stocks~service.application#docker.image::ansible@docker.engine->remote.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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 }}' - retailer.service.stocks~service.application#docker.image::ansible@gcp.cloudrun: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: touch service - register: service - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.service.yaml' - - name: create service - ansible.builtin.copy: - dest: '{{ service.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - apiVersion: serving.knative.dev/v1 - kind: Service - metadata: - name: '{{ SELF.application_name }}' - labels: - cloud.googleapis.com/location: '{{ SELF.gcp_region }}' - annotations: - run.googleapis.com/ingress: all - spec: - template: - spec: - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - containerPort: '{{ SELF.application_port }}' - env: [] - - name: apply service - ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet - args: - executable: /bin/bash - - name: touch policy - register: policy - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.policy.yaml' - - name: fill policy - ansible.builtin.copy: - dest: '{{ policy.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - bindings: - - members: - - allUsers - role: roles/run.invoker - - name: apply policy - ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - - name: describe service - register: service_description - ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - retailer.service.stocks~service.application#docker.image::ansible@kubernetes.cluster: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: create deployment - kubernetes.core.k8s: - wait: true - definition: - 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 }}' - - name: create service - kubernetes.core.k8s: - definition: - 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 - 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 }}' - retailer.service.stocks~service.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.stocks~service.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.stocks~service.application#zip.archive::ansible@gcp.appengine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: enable GCP AppEngine - ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - register: app_create_command - failed_when: - - "'Created' not in app_create_command.stderr" - - "'already contains' not in app_create_command.stderr" - - name: create working directory - register: directory - ansible.builtin.tempfile: - state: directory - - name: extract deployment artifact in working directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ directory.path }}' - - name: create specification - ansible.builtin.copy: - dest: '{{ directory.path }}/app.yaml' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - instance_class: F1 - env_variables: {} - - name: create app - ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet - args: - executable: /bin/bash - - name: browse app - register: browse_app - ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ browse_app.stdout[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet - args: - executable: /bin/bash - retailer.service.stocks~software.application#apt.package::ansible@*->remote.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.stocks~software.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.stocks~software.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.stocks~service.application#docker.image::terraform@docker.engine->local.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: unix:///var/run/docker.sock - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.stocks~service.application#docker.image::terraform@docker.engine->remote.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 - ssh_opts: - - '-i' - - '{{ SELF.os_ssh_key_file }}' - - '-o' - - IdentitiesOnly=yes - - '-o' - - BatchMode=yes - - '-o' - - UserKnownHostsFile=/dev/null - - '-o' - - StrictHostKeyChecking=no - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.stocks~service.application#docker.image::terraform@gcp.cloudrun: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' - resource: - google_cloud_run_v2_service: - application: - - ingress: INGRESS_TRAFFIC_ALL - location: '{{ SELF.gcp_region }}' - name: '{{ SELF.application_name }}' - template: - - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - container_port: '{{ SELF.application_port }}' - env: [] - google_cloud_run_service_iam_binding: - application: - - location: '{{ SELF.gcp_region }}' - members: - - allUsers - role: roles/run.invoker - service: '{{ SELF.application_name }}' - retailer.service.stocks~service.application#docker.image::terraform@kubernetes.cluster: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - kubernetes: - source: hashicorp/kubernetes - version: 2.31.0 - required_version: '>= 0.14.0' - provider: - kubernetes: - - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} - client_key: ${file("{{ SELF.k8s_client_key_file }}")} - cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} - host: '{{ SELF.k8s_host }}' - resource: - kubernetes_deployment_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - selector: - - match_labels: - app: '{{ SELF.application_name }}' - template: - - metadata: - - labels: - app: '{{ SELF.application_name }}' - spec: - - container: - - env: [] - image: '{{ ".artifacts::docker_image::file" | eval }}' - name: '{{ SELF.application_name }}' - port: - - container_port: '{{ SELF.application_port }}' - kubernetes_service_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - port: - - name: '{{ SELF.application_protocol }}' - port: '{{ SELF.application_port }}' - target_port: '{{ SELF.application_port }}' - selector: - app: '{{ SELF.application_name }}' - type: ClusterIP - retailer.service.stocks~service.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.stocks - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.stocks {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.stocks -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.stocks.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.stocks.sh - - sudo bash /tmp/configure-retailer.service.stocks.sh - - sudo bash /tmp/start-retailer.service.stocks.sh - - inline: - - sudo bash /tmp/stop-retailer.service.stocks.sh - - sudo bash /tmp/delete-retailer.service.stocks.sh - when: destroy - retailer.service.stocks~service.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.stocks - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.stocks {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.stocks -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.stocks.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.stocks.sh - - sudo bash /tmp/configure-retailer.service.stocks.sh - - sudo bash /tmp/start-retailer.service.stocks.sh - - inline: - - sudo bash /tmp/stop-retailer.service.stocks.sh - - sudo bash /tmp/delete-retailer.service.stocks.sh - when: destroy - retailer.service.stocks~service.application#zip.archive::terraform@gcp.appengine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' - resource: - google_app_engine_standard_app_version: - app: - - delete_service_on_destroy: true - deployment: - - zip: - - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} - entrypoint: - - shell: '{{ SELF._management_start }}' - env_variables: {} - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - service_account: ${google_service_account.custom_service_account.email} - version_id: v1 - google_project_iam_member: - gae_api: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/compute.networkUser - storage_viewer: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/storage.objectViewer - google_service_account: - custom_service_account: - - account_id: '{{ SELF.application_name }}-account' - display_name: Custom Service Account - google_storage_bucket: - bucket: - - location: EU - name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' - google_storage_bucket_object: - object: - - bucket: ${google_storage_bucket.bucket.name} - name: object.zip - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - retailer.service.stocks~software.application#apt.archive::terraform@*->remote.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.stocks {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-retailer.service.stocks.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.stocks.sh - - sudo bash /tmp/configure-retailer.service.stocks.sh - - sudo bash /tmp/start-retailer.service.stocks.sh - - inline: - - sudo bash /tmp/stop-retailer.service.stocks.sh - - sudo bash /tmp/delete-retailer.service.stocks.sh - when: destroy - retailer.service.stocks~software.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.stocks - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.stocks {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.stocks -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.stocks.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.stocks.sh - - sudo bash /tmp/configure-retailer.service.stocks.sh - - sudo bash /tmp/start-retailer.service.stocks.sh - - inline: - - sudo bash /tmp/stop-retailer.service.stocks.sh - - sudo bash /tmp/delete-retailer.service.stocks.sh - when: destroy - retailer.service.stocks~software.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.stocks - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.stocks {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.stocks -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.stocks.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.stocks.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.stocks.sh - - sudo bash /tmp/configure-retailer.service.stocks.sh - - sudo bash /tmp/start-retailer.service.stocks.sh - - inline: - - sudo bash /tmp/stop-retailer.service.stocks.sh - - sudo bash /tmp/delete-retailer.service.stocks.sh - when: destroy - retailer.service.stocks~service.application#docker.image::kubernetes@kubernetes.cluster: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: 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 }} 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 - retailer.service.stocks~service.application#docker.image::compose@docker.engine->local.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 - retailer.service.stocks~service.application#docker.image::compose@docker.engine->remote.machine: - derived_from: retailer.service.stocks - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 }}' - retailer.service.orders~service.application#docker.image::ansible@docker.engine->local.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: stop container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - state: absent - retailer.service.orders~service.application#docker.image::ansible@docker.engine->remote.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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 }}' - retailer.service.orders~service.application#docker.image::ansible@gcp.cloudrun: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: touch service - register: service - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.service.yaml' - - name: create service - ansible.builtin.copy: - dest: '{{ service.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - apiVersion: serving.knative.dev/v1 - kind: Service - metadata: - name: '{{ SELF.application_name }}' - labels: - cloud.googleapis.com/location: '{{ SELF.gcp_region }}' - annotations: - run.googleapis.com/ingress: all - spec: - template: - spec: - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - containerPort: '{{ SELF.application_port }}' - env: [] - - name: apply service - ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet - args: - executable: /bin/bash - - name: touch policy - register: policy - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.policy.yaml' - - name: fill policy - ansible.builtin.copy: - dest: '{{ policy.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - bindings: - - members: - - allUsers - role: roles/run.invoker - - name: apply policy - ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - - name: describe service - register: service_description - ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - retailer.service.orders~service.application#docker.image::ansible@kubernetes.cluster: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: create deployment - kubernetes.core.k8s: - wait: true - definition: - 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 }}' - - name: create service - kubernetes.core.k8s: - definition: - 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 - 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 }}' - retailer.service.orders~service.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.orders~service.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.orders~service.application#zip.archive::ansible@gcp.appengine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: enable GCP AppEngine - ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - register: app_create_command - failed_when: - - "'Created' not in app_create_command.stderr" - - "'already contains' not in app_create_command.stderr" - - name: create working directory - register: directory - ansible.builtin.tempfile: - state: directory - - name: extract deployment artifact in working directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ directory.path }}' - - name: create specification - ansible.builtin.copy: - dest: '{{ directory.path }}/app.yaml' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - instance_class: F1 - env_variables: {} - - name: create app - ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet - args: - executable: /bin/bash - - name: browse app - register: browse_app - ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ browse_app.stdout[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet - args: - executable: /bin/bash - retailer.service.orders~software.application#apt.package::ansible@*->remote.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.orders~software.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.orders~software.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.orders~service.application#docker.image::terraform@docker.engine->local.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: unix:///var/run/docker.sock - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.orders~service.application#docker.image::terraform@docker.engine->remote.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 - ssh_opts: - - '-i' - - '{{ SELF.os_ssh_key_file }}' - - '-o' - - IdentitiesOnly=yes - - '-o' - - BatchMode=yes - - '-o' - - UserKnownHostsFile=/dev/null - - '-o' - - StrictHostKeyChecking=no - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.orders~service.application#docker.image::terraform@gcp.cloudrun: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' - resource: - google_cloud_run_v2_service: - application: - - ingress: INGRESS_TRAFFIC_ALL - location: '{{ SELF.gcp_region }}' - name: '{{ SELF.application_name }}' - template: - - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - container_port: '{{ SELF.application_port }}' - env: [] - google_cloud_run_service_iam_binding: - application: - - location: '{{ SELF.gcp_region }}' - members: - - allUsers - role: roles/run.invoker - service: '{{ SELF.application_name }}' - retailer.service.orders~service.application#docker.image::terraform@kubernetes.cluster: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - kubernetes: - source: hashicorp/kubernetes - version: 2.31.0 - required_version: '>= 0.14.0' - provider: - kubernetes: - - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} - client_key: ${file("{{ SELF.k8s_client_key_file }}")} - cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} - host: '{{ SELF.k8s_host }}' - resource: - kubernetes_deployment_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - selector: - - match_labels: - app: '{{ SELF.application_name }}' - template: - - metadata: - - labels: - app: '{{ SELF.application_name }}' - spec: - - container: - - env: [] - image: '{{ ".artifacts::docker_image::file" | eval }}' - name: '{{ SELF.application_name }}' - port: - - container_port: '{{ SELF.application_port }}' - kubernetes_service_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - port: - - name: '{{ SELF.application_protocol }}' - port: '{{ SELF.application_port }}' - target_port: '{{ SELF.application_port }}' - selector: - app: '{{ SELF.application_name }}' - type: ClusterIP - retailer.service.orders~service.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.orders - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.orders {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.orders -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.orders.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.orders.sh - - sudo bash /tmp/configure-retailer.service.orders.sh - - sudo bash /tmp/start-retailer.service.orders.sh - - inline: - - sudo bash /tmp/stop-retailer.service.orders.sh - - sudo bash /tmp/delete-retailer.service.orders.sh - when: destroy - retailer.service.orders~service.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.orders - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.orders {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.orders -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.orders.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.orders.sh - - sudo bash /tmp/configure-retailer.service.orders.sh - - sudo bash /tmp/start-retailer.service.orders.sh - - inline: - - sudo bash /tmp/stop-retailer.service.orders.sh - - sudo bash /tmp/delete-retailer.service.orders.sh - when: destroy - retailer.service.orders~service.application#zip.archive::terraform@gcp.appengine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' - resource: - google_app_engine_standard_app_version: - app: - - delete_service_on_destroy: true - deployment: - - zip: - - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} - entrypoint: - - shell: '{{ SELF._management_start }}' - env_variables: {} - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - service_account: ${google_service_account.custom_service_account.email} - version_id: v1 - google_project_iam_member: - gae_api: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/compute.networkUser - storage_viewer: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/storage.objectViewer - google_service_account: - custom_service_account: - - account_id: '{{ SELF.application_name }}-account' - display_name: Custom Service Account - google_storage_bucket: - bucket: - - location: EU - name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' - google_storage_bucket_object: - object: - - bucket: ${google_storage_bucket.bucket.name} - name: object.zip - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - retailer.service.orders~software.application#apt.archive::terraform@*->remote.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.orders {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-retailer.service.orders.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.orders.sh - - sudo bash /tmp/configure-retailer.service.orders.sh - - sudo bash /tmp/start-retailer.service.orders.sh - - inline: - - sudo bash /tmp/stop-retailer.service.orders.sh - - sudo bash /tmp/delete-retailer.service.orders.sh - when: destroy - retailer.service.orders~software.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.orders - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.orders {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.orders -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.orders.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.orders.sh - - sudo bash /tmp/configure-retailer.service.orders.sh - - sudo bash /tmp/start-retailer.service.orders.sh - - inline: - - sudo bash /tmp/stop-retailer.service.orders.sh - - sudo bash /tmp/delete-retailer.service.orders.sh - when: destroy - retailer.service.orders~software.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.orders - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.orders {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.orders -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.orders.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.orders.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.orders.sh - - sudo bash /tmp/configure-retailer.service.orders.sh - - sudo bash /tmp/start-retailer.service.orders.sh - - inline: - - sudo bash /tmp/stop-retailer.service.orders.sh - - sudo bash /tmp/delete-retailer.service.orders.sh - when: destroy - retailer.service.orders~service.application#docker.image::kubernetes@kubernetes.cluster: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: 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 }} 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 - retailer.service.orders~service.application#docker.image::compose@docker.engine->local.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 - retailer.service.orders~service.application#docker.image::compose@docker.engine->remote.machine: - derived_from: retailer.service.orders - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 }}' - retailer.service.global~service.application#docker.image::ansible@docker.engine->local.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: stop container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - state: absent - retailer.service.global~service.application#docker.image::ansible@docker.engine->remote.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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 }}' - retailer.service.global~service.application#docker.image::ansible@gcp.cloudrun: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: touch service - register: service - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.service.yaml' - - name: create service - ansible.builtin.copy: - dest: '{{ service.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - apiVersion: serving.knative.dev/v1 - kind: Service - metadata: - name: '{{ SELF.application_name }}' - labels: - cloud.googleapis.com/location: '{{ SELF.gcp_region }}' - annotations: - run.googleapis.com/ingress: all - spec: - template: - spec: - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - containerPort: '{{ SELF.application_port }}' - env: [] - - name: apply service - ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet - args: - executable: /bin/bash - - name: touch policy - register: policy - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.policy.yaml' - - name: fill policy - ansible.builtin.copy: - dest: '{{ policy.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - bindings: - - members: - - allUsers - role: roles/run.invoker - - name: apply policy - ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - - name: describe service - register: service_description - ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - retailer.service.global~service.application#docker.image::ansible@kubernetes.cluster: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: create deployment - kubernetes.core.k8s: - wait: true - definition: - 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 }}' - - name: create service - kubernetes.core.k8s: - definition: - 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 - 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 }}' - retailer.service.global~service.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.global~service.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.global~service.application#zip.archive::ansible@gcp.appengine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: enable GCP AppEngine - ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - register: app_create_command - failed_when: - - "'Created' not in app_create_command.stderr" - - "'already contains' not in app_create_command.stderr" - - name: create working directory - register: directory - ansible.builtin.tempfile: - state: directory - - name: extract deployment artifact in working directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ directory.path }}' - - name: create specification - ansible.builtin.copy: - dest: '{{ directory.path }}/app.yaml' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - instance_class: F1 - env_variables: {} - - name: create app - ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet - args: - executable: /bin/bash - - name: browse app - register: browse_app - ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ browse_app.stdout[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet - args: - executable: /bin/bash - retailer.service.global~software.application#apt.package::ansible@*->remote.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.global~software.application#tar.archive::ansible@*->remote.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.global~software.application#zip.archive::ansible@*->remote.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - retailer.service.global~service.application#docker.image::terraform@docker.engine->local.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: unix:///var/run/docker.sock - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.global~service.application#docker.image::terraform@docker.engine->remote.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 - ssh_opts: - - '-i' - - '{{ SELF.os_ssh_key_file }}' - - '-o' - - IdentitiesOnly=yes - - '-o' - - BatchMode=yes - - '-o' - - UserKnownHostsFile=/dev/null - - '-o' - - StrictHostKeyChecking=no - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - retailer.service.global~service.application#docker.image::terraform@gcp.cloudrun: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' - resource: - google_cloud_run_v2_service: - application: - - ingress: INGRESS_TRAFFIC_ALL - location: '{{ SELF.gcp_region }}' - name: '{{ SELF.application_name }}' - template: - - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - container_port: '{{ SELF.application_port }}' - env: [] - google_cloud_run_service_iam_binding: - application: - - location: '{{ SELF.gcp_region }}' - members: - - allUsers - role: roles/run.invoker - service: '{{ SELF.application_name }}' - retailer.service.global~service.application#docker.image::terraform@kubernetes.cluster: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - kubernetes: - source: hashicorp/kubernetes - version: 2.31.0 - required_version: '>= 0.14.0' - provider: - kubernetes: - - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} - client_key: ${file("{{ SELF.k8s_client_key_file }}")} - cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} - host: '{{ SELF.k8s_host }}' - resource: - kubernetes_deployment_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - selector: - - match_labels: - app: '{{ SELF.application_name }}' - template: - - metadata: - - labels: - app: '{{ SELF.application_name }}' - spec: - - container: - - env: [] - image: '{{ ".artifacts::docker_image::file" | eval }}' - name: '{{ SELF.application_name }}' - port: - - container_port: '{{ SELF.application_port }}' - kubernetes_service_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - port: - - name: '{{ SELF.application_protocol }}' - port: '{{ SELF.application_port }}' - target_port: '{{ SELF.application_port }}' - selector: - app: '{{ SELF.application_name }}' - type: ClusterIP - retailer.service.global~service.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.global - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.global {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.global -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.global.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.global.sh - - sudo bash /tmp/configure-retailer.service.global.sh - - sudo bash /tmp/start-retailer.service.global.sh - - inline: - - sudo bash /tmp/stop-retailer.service.global.sh - - sudo bash /tmp/delete-retailer.service.global.sh - when: destroy - retailer.service.global~service.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.global - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.global {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.global -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-retailer.service.global.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.global.sh - - sudo bash /tmp/configure-retailer.service.global.sh - - sudo bash /tmp/start-retailer.service.global.sh - - inline: - - sudo bash /tmp/stop-retailer.service.global.sh - - sudo bash /tmp/delete-retailer.service.global.sh - when: destroy - retailer.service.global~service.application#zip.archive::terraform@gcp.appengine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' - resource: - google_app_engine_standard_app_version: - app: - - delete_service_on_destroy: true - deployment: - - zip: - - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} - entrypoint: - - shell: '{{ SELF._management_start }}' - env_variables: {} - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - service_account: ${google_service_account.custom_service_account.email} - version_id: v1 - google_project_iam_member: - gae_api: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/compute.networkUser - storage_viewer: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/storage.objectViewer - google_service_account: - custom_service_account: - - account_id: '{{ SELF.application_name }}-account' - display_name: Custom Service Account - google_storage_bucket: - bucket: - - location: EU - name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' - google_storage_bucket_object: - object: - - bucket: ${google_storage_bucket.bucket.name} - name: object.zip - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - retailer.service.global~software.application#apt.archive::terraform@*->remote.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.global {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-retailer.service.global.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.global.sh - - sudo bash /tmp/configure-retailer.service.global.sh - - sudo bash /tmp/start-retailer.service.global.sh - - inline: - - sudo bash /tmp/stop-retailer.service.global.sh - - sudo bash /tmp/delete-retailer.service.global.sh - when: destroy - retailer.service.global~software.application#tar.archive::terraform@*->remote.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.global - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.global {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-retailer.service.global -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.global.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.global.sh - - sudo bash /tmp/configure-retailer.service.global.sh - - sudo bash /tmp/start-retailer.service.global.sh - - inline: - - sudo bash /tmp/stop-retailer.service.global.sh - - sudo bash /tmp/delete-retailer.service.global.sh - when: destroy - retailer.service.global~software.application#zip.archive::terraform@*->remote.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-retailer.service.global - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-retailer.service.global {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-retailer.service.global -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-retailer.service.global.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-retailer.service.global.sh - remote-exec: - - inline: - - sudo bash /tmp/create-retailer.service.global.sh - - sudo bash /tmp/configure-retailer.service.global.sh - - sudo bash /tmp/start-retailer.service.global.sh - - inline: - - sudo bash /tmp/stop-retailer.service.global.sh - - sudo bash /tmp/delete-retailer.service.global.sh - when: destroy - retailer.service.global~service.application#docker.image::kubernetes@kubernetes.cluster: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: 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 }} 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 - retailer.service.global~service.application#docker.image::compose@docker.engine->local.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 - retailer.service.global~service.application#docker.image::compose@docker.engine->remote.machine: - derived_from: retailer.service.global - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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---industry---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml deleted file mode 100644 index 717e952e1c..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-core.yaml +++ /dev/null @@ -1,2502 +0,0 @@ -################################################### -# -# WARNING: Do not edit! This file is autogenerated! -# -################################################### - -tosca_definitions_version: tosca_simple_yaml_1_3 -description: TOSCA Profile for OpenTOSCA Vintner (Core) -metadata: - vintner_normative: 'true' - template_name: TOSCA Vintner Profile (Core) - template_author: Miles Stötzner - template_contact: miles.stoetzner@iste.uni-stuttgart.de - template_link: https://vintner.opentosca.org - template_version: 1.0.0-draft - template_id: tosca-vintner-profile - template_license: https://www.apache.org/licenses/LICENSE-2.0 - acknowledgments: Partially funded by the [German Federal Ministry for Economic Affairs and Climate Action (BMWK)](https://www.bmwk.de) as part of the research project [SofDCar (19S21002)](https://sofdcar.de). - vintner_orchestrator: unfurl -artifact_types: - artifact: - derived_from: tosca.artifacts.Root - source.archive: - derived_from: artifact - description: application packaged as archive - properties: - extra_opts: - type: list - entry_schema: - type: string - required: false - default: [] - system.package: - derived_from: artifact - properties: - script: - type: string - required: false - description: URL of an installation script - default: '' - repository: - type: string - required: false - description: name of the repository (required if source is set) - default: '' - key: - type: string - required: false - description: URL of the apt key which signs the apt repository (required if source is set) - default: '' - source: - type: string - required: false - description: source of the repository - default: '' - dependencies: - type: string - required: false - description: Comma separated list of apt packages that are additionally installed - default: '' - env: - type: string - required: false - description: Space separated env variables - default: '' - container.image: - derived_from: artifact - description: expects image reference in "file" - machine.image: - derived_from: artifact - description: expects image reference in "file" - dbms.image: - derived_from: artifact - description: expects image reference in "file" - cache.image: - derived_from: artifact - description: expects image reference in "file" -interface_types: - interface: - derived_from: tosca.interfaces.Root - metadata: - vintner_normative: 'true' - management: - derived_from: interface - metadata: - vintner_normative: 'true' - operations: - create: - description: management lifecycle create operation. - configure: - description: management lifecycle configure operation. - start: - description: management lifecycle start operation. - stop: - description: management lifecycle stop operation. - delete: - description: management lifecycle delete operation. -node_types: - node: - derived_from: tosca.nodes.Root - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - cloud.provider: - derived_from: node - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - capabilities: - host: - type: tosca.capabilities.Compute - cloud.service: - derived_from: node - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - capabilities: - host: - type: tosca.capabilities.Compute - requirements: - - host: - capability: tosca.capabilities.Compute - relationship: tosca.relationships.HostedOn - software.application: - derived_from: node - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - properties: - application_name: - type: string - _management_create: - type: string - metadata: - vintner_ignore: 'true' - default: - eval: - python: '{{ "project" | get_dir }}/vintner_utils.py#get_operation' - args: - - management - - create - _management_configure: - type: string - metadata: - vintner_ignore: 'true' - default: - eval: - python: '{{ "project" | get_dir }}/vintner_utils.py#get_operation' - args: - - management - - configure - _management_start: - type: string - metadata: - vintner_ignore: 'true' - default: - eval: - python: '{{ "project" | get_dir }}/vintner_utils.py#get_operation' - args: - - management - - start - _management_stop: - type: string - metadata: - vintner_ignore: 'true' - default: - eval: - python: '{{ "project" | get_dir }}/vintner_utils.py#get_operation' - args: - - management - - stop - _management_delete: - type: string - metadata: - vintner_ignore: 'true' - default: - eval: - python: '{{ "project" | get_dir }}/vintner_utils.py#get_operation' - args: - - management - - delete - requirements: - - host: - capability: tosca.capabilities.Compute - relationship: tosca.relationships.HostedOn - interfaces: - management: - type: management - service.application: - derived_from: software.application - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - properties: - application_language: - type: string - application_port: - type: string - metadata: - vintner_name: PORT - application_protocol: - type: string - attributes: - application_address: - type: string - application_endpoint: - type: string - default: - concat: - - eval: .::application_protocol - - '://' - - eval: .::application_address - - ':' - - eval: .::application_port - software.runtime: - derived_from: software.application - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - capabilities: - host: - type: tosca.capabilities.Compute - container.runtime: - derived_from: software.runtime - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - machine: - derived_from: node - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - properties: - machine_name: - type: string - attributes: - application_address: - type: string - management_address: - type: string - local.machine: - derived_from: machine - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - capabilities: - host: - type: tosca.capabilities.Compute - remote.machine: - derived_from: machine - metadata: - vintner_normative: 'true' - properties: - machine_name: - type: string - ports: - type: list - entry_schema: - type: string - flavor: - type: string - default: m1.medium - network: - type: string - ssh_user: - type: string - ssh_key_name: - type: string - ssh_key_file: - type: string - capabilities: - host: - type: tosca.capabilities.Compute - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address - attributes: - application_address: - default: - eval: .::management_address - virtual.machine: - derived_from: remote.machine - physical.machine: - derived_from: remote.machine - database: - derived_from: node - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - requirements: - - host: - capability: tosca.capabilities.Compute - relationship: tosca.relationships.HostedOn - relational.database: - derived_from: database - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - dbms: - derived_from: software.application - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - relational.dbms: - derived_from: dbms - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - cache: - derived_from: software.application - storage: - derived_from: node - block.storage: - derived_from: storage - object.storage: - derived_from: storage - file.storage: - derived_from: storage - bucket: - derived_from: object.storage - metadata: - vintner_normative: 'true' - properties: - bucket_name: - type: string - bucket_dialect: - type: string - attributes: - bucket_endpoint: - type: string - bucket_token: - type: string - requirements: - - host: - capability: tosca.capabilities.Compute - relationship: tosca.relationships.HostedOn - ingress: - derived_from: node - metadata: - vintner_normative: 'true' - properties: - application_name: - type: string - default: - eval: .::.requirements::[.name=application]::.target::application_name - application_port: - type: string - default: - eval: .::.requirements::[.name=application]::.target::application_port - application_protocol: - type: string - default: - eval: .::.requirements::[.name=application]::.target::application_protocol - attributes: - application_address: - type: string - requirements: - - application: - capability: tosca.capabilities.Endpoint - relationship: tosca.relationships.ConnectsTo - - host: - capability: tosca.capabilities.Compute - relationship: tosca.relationships.HostedOn - - # [OPENTOSCA_VINTNER_GENERATION_MARK] - - ################################################################ - # - # WARNING: Do not edit! This following content is autogenerated! - # - ################################################################ - - virtual.machine~virtual.machine#machine.image::ansible@openstack.provider: - derived_from: virtual.machine - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_region_name: - type: string - default: - get_input: os_region_name - os_auth_type: - type: string - default: - get_input: os_auth_type - os_auth_url: - type: string - default: - get_input: os_auth_url - os_identity_api_version: - type: string - default: - get_input: os_identity_api_version - os_interface: - type: string - default: - get_input: os_interface - os_application_credential_id: - type: string - default: - get_input: os_application_credential_id - os_application_credential_secret: - type: string - default: - get_input: os_application_credential_secret - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - OS_AUTH_TYPE: - eval: .::os_auth_type - OS_AUTH_URL: - eval: .::os_auth_url - OS_IDENTITY_API_VERSION: - eval: .::os_identity_api_version - OS_REGION_NAME: - eval: .::os_region_name - OS_INTERFACE: - eval: .::os_interface - OS_APPLICATION_CREDENTIAL_ID: - eval: .::os_application_credential_id - OS_APPLICATION_CREDENTIAL_SECRET: - eval: .::os_application_credential_secret - inputs: - playbook: - q: - - name: Create security group - openstack.cloud.security_group: - name: '{{ SELF.machine_name }}' - - name: Open ports - openstack.cloud.security_group_rule: - security_group: '{{ SELF.machine_name }}' - protocol: tcp - port_range_min: '{{ item }}' - port_range_max: '{{ item }}' - remote_ip_prefix: 0.0.0.0/0 - direction: ingress - ethertype: IPv4 - loop: '{{ SELF.ports | join("::") | split("::") | map("int") }}' - - name: Create VM - openstack.cloud.server: - state: present - name: '{{ SELF.machine_name }}' - image: '{{ ".artifacts::machine_image::file" | eval }}' - key_name: default - flavor: '{{ SELF.flavor }}' - network: '{{ SELF.network }}' - security_groups: "{{ 'default,' + SELF.machine_name }}" - auto_ip: false - timeout: 360 - register: server_info - - name: Set attributes - set_fact: - management_address: '{{ server_info.server.accessIPv4 }}' - resultTemplate: | - name: SELF - attributes: - management_address: '{{ outputs.management_address | trim }}' - outputs: - management_address: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: Delete VM - openstack.cloud.server: - state: absent - name: '{{ SELF.machine_name }}' - delete_fip: true - timeout: 360 - - name: Delete security group - openstack.cloud.security_group: - state: absent - name: '{{ SELF.machine_name }}' - virtual.machine~virtual.machine#machine.image::terraform@openstack.provider: - derived_from: virtual.machine - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_region_name: - type: string - default: - get_input: os_region_name - os_auth_type: - type: string - default: - get_input: os_auth_type - os_auth_url: - type: string - default: - get_input: os_auth_url - os_identity_api_version: - type: string - default: - get_input: os_identity_api_version - os_interface: - type: string - default: - get_input: os_interface - os_application_credential_id: - type: string - default: - get_input: os_application_credential_id - os_application_credential_secret: - type: string - default: - get_input: os_application_credential_secret - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - management_address: management_address - inputs: - main: - terraform: - - required_providers: - - openstack: - source: terraform-provider-openstack/openstack - version: ~> 1.48.0 - required_version: '>= 0.14.0' - provider: - openstack: - - application_credential_id: '{{ SELF.os_application_credential_id }}' - application_credential_secret: '{{ SELF.os_application_credential_secret }}' - auth_url: '{{ SELF.os_auth_url }}' - region: '{{ SELF.os_region_name }}' - output: - management_address: - - value: ${yamldecode(openstack_compute_instance_v2.machine.access_ip_v4)} - resource: - openstack_compute_instance_v2: - machine: - - flavor_name: '{{ SELF.flavor }}' - image_name: '{{ ".artifacts::machine_image::file" | eval }}' - key_pair: default - name: '{{ SELF.machine_name }}' - network: - - name: '{{ SELF.network }}' - security_groups: - - default - - ${openstack_networking_secgroup_v2.ports.name} - openstack_networking_secgroup_rule_v2: - port: - - direction: ingress - ethertype: IPv4 - for_each: ${toset(split("::", "{{ SELF.ports | join("::") }}"))} - port_range_max: ${each.value} - port_range_min: ${each.value} - protocol: tcp - remote_ip_prefix: 0.0.0.0/0 - security_group_id: ${openstack_networking_secgroup_v2.ports.id} - openstack_networking_secgroup_v2: - ports: - - name: '{{ SELF.machine_name }}' - cache~software.application#apt.package::ansible@*->remote.machine: - derived_from: cache - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - cache~software.application#tar.archive::ansible@*->remote.machine: - derived_from: cache - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - cache~software.application#zip.archive::ansible@*->remote.machine: - derived_from: cache - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - cache~software.application#apt.archive::terraform@*->remote.machine: - derived_from: cache - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-cache {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-cache.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-cache.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-cache.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-cache.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-cache.sh - remote-exec: - - inline: - - sudo bash /tmp/create-cache.sh - - sudo bash /tmp/configure-cache.sh - - sudo bash /tmp/start-cache.sh - - inline: - - sudo bash /tmp/stop-cache.sh - - sudo bash /tmp/delete-cache.sh - when: destroy - cache~software.application#tar.archive::terraform@*->remote.machine: - derived_from: cache - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-cache - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-cache {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-cache -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-cache.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-cache.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-cache.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-cache.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-cache.sh - remote-exec: - - inline: - - sudo bash /tmp/create-cache.sh - - sudo bash /tmp/configure-cache.sh - - sudo bash /tmp/start-cache.sh - - inline: - - sudo bash /tmp/stop-cache.sh - - sudo bash /tmp/delete-cache.sh - when: destroy - cache~software.application#zip.archive::terraform@*->remote.machine: - derived_from: cache - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-cache - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-cache {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-cache -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-cache.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-cache.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-cache.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-cache.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-cache.sh - remote-exec: - - inline: - - sudo bash /tmp/create-cache.sh - - sudo bash /tmp/configure-cache.sh - - sudo bash /tmp/start-cache.sh - - inline: - - sudo bash /tmp/stop-cache.sh - - sudo bash /tmp/delete-cache.sh - when: destroy - bucket~bucket::ansible@gcp.cloudstorage: - derived_from: bucket - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: [] - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: [] - bucket~bucket::ansible@minio.server->*->local.machine: - derived_from: bucket - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: [] - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: [] - bucket~bucket::ansible@minio.server->*->remote.machine: - derived_from: bucket - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: [] - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: [] - bucket~bucket::ansible@minio.server->kubernetes.cluster: - derived_from: bucket - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: [] - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: [] - bucket~bucket#cache.image::ansible@gcp.memorystore: - derived_from: bucket - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: [] - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: [] - bucket~bucket::terraform@gcp.cloudstorage: - derived_from: bucket - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - environment: - GOOGLE_APPLICATION_CREDENTIALS: - eval: .::gcp_service_account_file - delete: - implementation: - primary: Terraform - environment: - GOOGLE_APPLICATION_CREDENTIALS: - eval: .::gcp_service_account_file - defaults: - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - mysql: - source: petoju/mysql - version: 3.0.48 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - resource: {} - bucket~bucket::terraform@minio.server->*->local.machine: - derived_from: bucket - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: [] - provider: {} - resource: {} - bucket~bucket::terraform@minio.server->*->remote.machine: - derived_from: bucket - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - environment: - GOOGLE_APPLICATION_CREDENTIALS: - eval: .::gcp_service_account_file - delete: - implementation: - primary: Terraform - environment: - GOOGLE_APPLICATION_CREDENTIALS: - eval: .::gcp_service_account_file - defaults: - inputs: - main: - terraform: [] - provider: {} - resource: {} - bucket~bucket::terraform@minio.server->kubernetes.cluster: - derived_from: bucket - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - environment: - GOOGLE_APPLICATION_CREDENTIALS: - eval: .::gcp_service_account_file - delete: - implementation: - primary: Terraform - environment: - GOOGLE_APPLICATION_CREDENTIALS: - eval: .::gcp_service_account_file - defaults: - inputs: - main: - terraform: [] - provider: {} - resource: {} - ingress~ingress::ansible@kubernetes.cluster: - derived_from: ingress - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: not implemented - interfaces: - Standard: - operations: - create: - 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: apply service - kubernetes.core.k8s: - definition: - apiVersion: v1 - kind: Service - metadata: - name: '{{ SELF.application_name }}-external' - namespace: default - spec: - ports: - - name: '{{ SELF.application_protocol }}' - port: 80 - targetPort: '{{ SELF.application_port }}' - selector: - app: '{{ SELF.application_name }}' - type: LoadBalancer - ingress~ingress::ansible@remote.machine: - derived_from: ingress - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::application_address - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: add apt key - ansible.builtin.apt_key: - url: https://dl.cloudsmith.io/public/caddy/stable/gpg.key - keyring: /usr/share/keyrings/caddy-stable-archive-keyring.gpg - state: present - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/caddy-stable-archive-keyring.gpg] https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main - filename: caddy-stable - state: present - - name: install package - ansible.builtin.apt: - name: caddy - state: present - update_cache: 'yes' - - name: configure caddy - ansible.builtin.copy: - dest: /etc/caddy/Caddyfile - content: | - :80 { - reverse_proxy localhost:{{ SELF.application_port }} - } - - name: restart caddy - ansible.builtin.systemd: - name: caddy - state: reloaded - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: not implemented - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - kubernetes: - source: hashicorp/kubernetes - version: 2.31.0 - required_version: '>= 0.14.0' - provider: - kubernetes: - - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} - client_key: ${file("{{ SELF.k8s_client_key_file }}")} - cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} - host: '{{ SELF.k8s_host }}' - resource: - kubernetes_service_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}-external' - wait_for_load_balancer: false - spec: - - port: - - name: '{{ SELF.application_protocol }}' - port: 80 - target_port: '{{ SELF.application_port }}' - selector: - app: '{{ SELF.application_name }}' - type: LoadBalancer - ingress~ingress::terraform@remote.machine: - derived_from: ingress - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::application_address - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - - #!/usr/bin/bash - set -e - - # Install caddy - apt-get install -y debian-keyring debian-archive-keyring apt-transport-https curl - curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/gpg.key | gpg --dearmor --yes -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg - curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt | tee /etc/apt/sources.list.d/caddy-stable.list - apt-get update - apt-get install caddy -y - - # Configure caddy - cat < /etc/caddy/Caddyfile - :80 { - reverse_proxy localhost:{{ SELF.application_port }} - } - EOF - - # Restart caddy - systemctl reload caddy - destination: /tmp/install-ingress.sh - remote-exec: - - inline: - - sudo bash /tmp/install-ingress.sh - ingress~ingress::kubernetes@kubernetes.cluster: - derived_from: ingress - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: not implemented - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: touch manifest - register: manifest - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.ingress.manifest.yaml' - - name: create manifest - ansible.builtin.copy: - dest: '{{ manifest.path }}' - content: '{{ service | to_yaml }}' - vars: - service: - apiVersion: v1 - kind: Service - metadata: - name: '{{ SELF.application_name }}-external' - spec: - ports: - - name: '{{ SELF.application_protocol }}' - port: '{{ SELF.application_port }}' - targetPort: '{{ SELF.application_port }}' - selector: - app: '{{ SELF.application_name }}' - type: LoadBalancer - - 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 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml deleted file mode 100644 index afb9977532..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile-extended.yaml +++ /dev/null @@ -1,16192 +0,0 @@ -################################################### -# -# WARNING: Do not edit! This file is autogenerated! -# -################################################### - -tosca_definitions_version: tosca_simple_yaml_1_3 -description: TOSCA Profile for OpenTOSCA Vintner (Extended) -metadata: - vintner_normative: 'true' - template_name: TOSCA Vintner Profile (Extended) - template_author: Miles Stötzner - template_contact: miles.stoetzner@iste.uni-stuttgart.de - template_link: https://vintner.opentosca.org - template_version: 1.0.0-draft - template_id: tosca-vintner-profile - template_license: https://www.apache.org/licenses/LICENSE-2.0 - acknowledgments: Partially funded by the [German Federal Ministry for Economic Affairs and Climate Action (BMWK)](https://www.bmwk.de) as part of the research project [SofDCar (19S21002)](https://sofdcar.de). - vintner_orchestrator: unfurl -imports: - - tosca-vintner-profile-core.yaml -artifact_types: - docker.image: - derived_from: container.image - description: expects image reference in "file" - zip.archive: - derived_from: source.archive - tar.archive: - derived_from: source.archive - apt.package: - derived_from: system.package - properties: - script: - type: string - required: false - description: URL of an installation script - repository: - type: string - required: false - description: name of the repository (required if source is set) - key: - type: string - required: false - description: URL of the apt key which signs the apt repository (required if source is set) - source: - type: string - required: false - description: source of the repository - dependencies: - type: string - required: false - description: Comma separated list of apt packages that are additionally installed - env: - type: string - required: false - description: Space separated env variables - default: '' -node_types: - nodejs.runtime: - derived_from: software.runtime - metadata: - vintner_normative: 'true' - properties: - application_name: - type: string - default: nodejs - artifacts: - apt_package: - type: apt.package - file: nodejs - properties: - script: https://deb.nodesource.com/setup_18.x - attributes: - management_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - capabilities: - host: - type: tosca.capabilities.Compute - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address - nodejs.service.application: - derived_from: service.application - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - properties: - application_language: - type: string - default: nodejs18 - interfaces: - management: - type: management - operations: - configure: npm ci - start: npm start - reactjs.service.application: - derived_from: service.application - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - properties: - application_language: - type: string - default: nodejs18 - python.runtime: - derived_from: software.runtime - metadata: - vintner_normative: 'true' - artifacts: - apt_package: - type: apt.package - file: python-is-python3 - properties: - dependencies: - type: string - default: python3 python3-pip python3-venv - attributes: - management_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - capabilities: - host: - type: tosca.capabilities.Compute - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address - python.service.application: - derived_from: service.application - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - properties: - application_language: - type: string - default: python3 - interfaces: - management: - type: management - operations: - configure: pip install -r requirements.txt - start: python main.py - go.service.application: - derived_from: service.application - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - properties: - application_language: - type: string - default: go122 - java.runtime: - derived_from: software.runtime - metadata: - vintner_normative: 'true' - properties: - application_name: - type: string - default: java - artifacts: - apt_package: - type: apt.package - file: openjdk-18-jre-headless - attributes: - management_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - capabilities: - host: - type: tosca.capabilities.Compute - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address - java.service.application: - derived_from: service.application - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - properties: - application_language: - type: string - default: java21 - dotnet.runtime: - derived_from: software.runtime - metadata: - vintner_normative: 'true' - properties: - application_name: - type: string - default: java - artifacts: - apt_package: - type: apt.package - file: dotnet-sdk-8.0 - attributes: - management_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - capabilities: - host: - type: tosca.capabilities.Compute - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address - csharp.service.application: - derived_from: service.application - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - properties: - application_language: - type: string - default: dotnet8 - binary.service.application: - derived_from: service.application - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - properties: - application_language: - type: string - default: binary - interfaces: - management: - type: management - operations: - start: ./{{ SELF.application_name }} - gcp.provider: - derived_from: cloud.provider - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - properties: - _hosting: - type: string - default: gcp - gcp_region: - type: string - gcp_service_account_file: - type: string - gcp_project: - type: string - interfaces: - Standard: - operations: - create: exit 0 - delete: exit 0 - gcp.service: - derived_from: cloud.service - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - properties: - _hosting: - type: string - default: gcp - gcp_service: - type: string - default: must-be-overridden - gcp.cloudrun: - derived_from: gcp.service - metadata: - vintner_normative: 'true' - properties: - gcp_service: - type: string - default: run.googleapis.com - gcp.cloudsql: - derived_from: gcp.service - metadata: - vintner_normative: 'true' - properties: - gcp_service: - type: string - default: sqladmin.googleapis.com - gcp.appengine: - derived_from: gcp.service - metadata: - vintner_normative: 'true' - properties: - gcp_service: - type: string - default: appengine.googleapis.com - requirements: - - build: - capability: tosca.capabilities.Root - relationship: tosca.relationships.DependsOn - - reporting: - capability: tosca.capabilities.Root - relationship: tosca.relationships.DependsOn - gcp.appenginereporting: - derived_from: gcp.service - metadata: - vintner_normative: 'true' - properties: - gcp_service: - type: string - default: appenginereporting.googleapis.com - gcp.cloudbuild: - derived_from: gcp.service - metadata: - vintner_normative: 'true' - properties: - gcp_service: - type: string - default: cloudbuild.googleapis.com - gcp.kubernetesengine: - derived_from: gcp.service - metadata: - vintner_normative: 'true' - properties: - gcp_service: - type: string - default: container.googleapis.com - gcp.cloudstorage: - derived_from: gcp.service - metadata: - vintner_normative: 'true' - properties: - gcp_service: - type: string - default: storage.googleapis.com - gcp.memorystore: - derived_from: gcp.service - metadata: - vintner_normative: 'true' - properties: - gcp_service: - type: string - default: redis.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: - application_name: - type: string - default: docker - _hosting: - type: string - default: docker - attributes: - management_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - capabilities: - host: - type: tosca.capabilities.Compute - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address - kubernetes.cluster: - derived_from: cloud.service - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - properties: - _hosting: - type: string - default: kubernetes - k8s_host: - type: string - k8s_ca_cert_file: - type: string - k8s_client_cert_file: - type: string - k8s_client_key_file: - type: string - capabilities: - host: - type: tosca.capabilities.Compute - interfaces: - Standard: - operations: - create: exit 0 - delete: exit 0 - openstack.provider: - derived_from: cloud.provider - metadata: - vintner_normative: 'true' - vintner_abstract: 'true' - properties: - _hosting: - type: string - default: openstack - os_region_name: - type: string - os_auth_type: - type: string - os_auth_url: - type: string - os_identity_api_version: - type: string - os_interface: - type: string - os_application_credential_id: - type: string - os_application_credential_secret: - type: string - interfaces: - Standard: - operations: - create: exit 0 - delete: exit 0 - mysql.dbms: - derived_from: relational.dbms - metadata: - vintner_normative: 'true' - properties: - dbms_name: - type: string - application_name: - type: string - default: - eval: .::dbms_name - dbms_password: - type: string - dbms_ssl_mode: - type: string - default: None - attributes: - application_address: - type: string - application_port: - type: string - management_address: - type: string - management_port: - type: string - capabilities: - host: - type: tosca.capabilities.Compute - requirements: - - host: - capability: tosca.capabilities.Compute - relationship: tosca.relationships.HostedOn - mysql.database: - derived_from: relational.database - metadata: - vintner_normative: 'true' - properties: - database_name: - type: string - database_user: - type: string - database_password: - type: string - attributes: - application_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::application_address - application_port: - type: string - default: - eval: .::.requirements::[.name=host]::.target::application_port - capabilities: - database: - type: tosca.capabilities.Endpoint.Database - requirements: - - host: - capability: tosca.capabilities.Compute - relationship: tosca.relationships.HostedOn - minio.server: - derived_from: service.application - metadata: - vintner_normative: 'true' - redis.server: - derived_from: cache - metadata: - vintner_normative: 'true' - properties: - cache_name: - type: string - cache_port: - type: string - application_protocol: - type: string - default: redis - application_name: - default: - eval: .::cache_name - application_port: - default: - eval: .::cache_port - - # [OPENTOSCA_VINTNER_GENERATION_MARK] - - ################################################################ - # - # WARNING: Do not edit! This following content is autogenerated! - # - ################################################################ - - nodejs.runtime~software.application#apt.package::ansible@*->remote.machine: - derived_from: nodejs.runtime - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - nodejs.runtime~software.application#tar.archive::ansible@*->remote.machine: - derived_from: nodejs.runtime - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: APPLICATION_NAME="{{ SELF.application_name }}" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - nodejs.runtime~software.application#zip.archive::ansible@*->remote.machine: - derived_from: nodejs.runtime - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: APPLICATION_NAME="{{ SELF.application_name }}" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - nodejs.runtime~software.application#apt.archive::terraform@*->remote.machine: - derived_from: nodejs.runtime - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-nodejs.runtime {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-nodejs.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-nodejs.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-nodejs.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-nodejs.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-nodejs.runtime.sh - remote-exec: - - inline: - - sudo bash /tmp/create-nodejs.runtime.sh - - sudo bash /tmp/configure-nodejs.runtime.sh - - sudo bash /tmp/start-nodejs.runtime.sh - - inline: - - sudo bash /tmp/stop-nodejs.runtime.sh - - sudo bash /tmp/delete-nodejs.runtime.sh - when: destroy - nodejs.runtime~software.application#tar.archive::terraform@*->remote.machine: - derived_from: nodejs.runtime - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-nodejs.runtime - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-nodejs.runtime {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-nodejs.runtime -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-nodejs.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-nodejs.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-nodejs.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-nodejs.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-nodejs.runtime.sh - remote-exec: - - inline: - - sudo bash /tmp/create-nodejs.runtime.sh - - sudo bash /tmp/configure-nodejs.runtime.sh - - sudo bash /tmp/start-nodejs.runtime.sh - - inline: - - sudo bash /tmp/stop-nodejs.runtime.sh - - sudo bash /tmp/delete-nodejs.runtime.sh - when: destroy - nodejs.runtime~software.application#zip.archive::terraform@*->remote.machine: - derived_from: nodejs.runtime - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-nodejs.runtime - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-nodejs.runtime {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-nodejs.runtime -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-nodejs.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-nodejs.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-nodejs.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-nodejs.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-nodejs.runtime.sh - remote-exec: - - inline: - - sudo bash /tmp/create-nodejs.runtime.sh - - sudo bash /tmp/configure-nodejs.runtime.sh - - sudo bash /tmp/start-nodejs.runtime.sh - - inline: - - sudo bash /tmp/stop-nodejs.runtime.sh - - sudo bash /tmp/delete-nodejs.runtime.sh - when: destroy - python.runtime~software.application#apt.package::ansible@*->remote.machine: - derived_from: python.runtime - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - python.runtime~software.application#tar.archive::ansible@*->remote.machine: - derived_from: python.runtime - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - python.runtime~software.application#zip.archive::ansible@*->remote.machine: - derived_from: python.runtime - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - python.runtime~software.application#apt.archive::terraform@*->remote.machine: - derived_from: python.runtime - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-python.runtime {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-python.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-python.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-python.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-python.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-python.runtime.sh - remote-exec: - - inline: - - sudo bash /tmp/create-python.runtime.sh - - sudo bash /tmp/configure-python.runtime.sh - - sudo bash /tmp/start-python.runtime.sh - - inline: - - sudo bash /tmp/stop-python.runtime.sh - - sudo bash /tmp/delete-python.runtime.sh - when: destroy - python.runtime~software.application#tar.archive::terraform@*->remote.machine: - derived_from: python.runtime - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-python.runtime - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-python.runtime {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-python.runtime -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-python.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-python.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-python.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-python.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-python.runtime.sh - remote-exec: - - inline: - - sudo bash /tmp/create-python.runtime.sh - - sudo bash /tmp/configure-python.runtime.sh - - sudo bash /tmp/start-python.runtime.sh - - inline: - - sudo bash /tmp/stop-python.runtime.sh - - sudo bash /tmp/delete-python.runtime.sh - when: destroy - python.runtime~software.application#zip.archive::terraform@*->remote.machine: - derived_from: python.runtime - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-python.runtime - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-python.runtime {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-python.runtime -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-python.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-python.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-python.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-python.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-python.runtime.sh - remote-exec: - - inline: - - sudo bash /tmp/create-python.runtime.sh - - sudo bash /tmp/configure-python.runtime.sh - - sudo bash /tmp/start-python.runtime.sh - - inline: - - sudo bash /tmp/stop-python.runtime.sh - - sudo bash /tmp/delete-python.runtime.sh - when: destroy - java.runtime~software.application#apt.package::ansible@*->remote.machine: - derived_from: java.runtime - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - java.runtime~software.application#tar.archive::ansible@*->remote.machine: - derived_from: java.runtime - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: APPLICATION_NAME="{{ SELF.application_name }}" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - java.runtime~software.application#zip.archive::ansible@*->remote.machine: - derived_from: java.runtime - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: APPLICATION_NAME="{{ SELF.application_name }}" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - java.runtime~software.application#apt.archive::terraform@*->remote.machine: - derived_from: java.runtime - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-java.runtime {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-java.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-java.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-java.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-java.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-java.runtime.sh - remote-exec: - - inline: - - sudo bash /tmp/create-java.runtime.sh - - sudo bash /tmp/configure-java.runtime.sh - - sudo bash /tmp/start-java.runtime.sh - - inline: - - sudo bash /tmp/stop-java.runtime.sh - - sudo bash /tmp/delete-java.runtime.sh - when: destroy - java.runtime~software.application#tar.archive::terraform@*->remote.machine: - derived_from: java.runtime - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-java.runtime - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-java.runtime {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-java.runtime -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-java.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-java.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-java.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-java.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-java.runtime.sh - remote-exec: - - inline: - - sudo bash /tmp/create-java.runtime.sh - - sudo bash /tmp/configure-java.runtime.sh - - sudo bash /tmp/start-java.runtime.sh - - inline: - - sudo bash /tmp/stop-java.runtime.sh - - sudo bash /tmp/delete-java.runtime.sh - when: destroy - java.runtime~software.application#zip.archive::terraform@*->remote.machine: - derived_from: java.runtime - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-java.runtime - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-java.runtime {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-java.runtime -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-java.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-java.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-java.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-java.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-java.runtime.sh - remote-exec: - - inline: - - sudo bash /tmp/create-java.runtime.sh - - sudo bash /tmp/configure-java.runtime.sh - - sudo bash /tmp/start-java.runtime.sh - - inline: - - sudo bash /tmp/stop-java.runtime.sh - - sudo bash /tmp/delete-java.runtime.sh - when: destroy - dotnet.runtime~software.application#apt.package::ansible@*->remote.machine: - derived_from: dotnet.runtime - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - dotnet.runtime~software.application#tar.archive::ansible@*->remote.machine: - derived_from: dotnet.runtime - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: APPLICATION_NAME="{{ SELF.application_name }}" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - dotnet.runtime~software.application#zip.archive::ansible@*->remote.machine: - derived_from: dotnet.runtime - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: APPLICATION_NAME="{{ SELF.application_name }}" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - dotnet.runtime~software.application#apt.archive::terraform@*->remote.machine: - derived_from: dotnet.runtime - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-dotnet.runtime {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-dotnet.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-dotnet.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-dotnet.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-dotnet.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-dotnet.runtime.sh - remote-exec: - - inline: - - sudo bash /tmp/create-dotnet.runtime.sh - - sudo bash /tmp/configure-dotnet.runtime.sh - - sudo bash /tmp/start-dotnet.runtime.sh - - inline: - - sudo bash /tmp/stop-dotnet.runtime.sh - - sudo bash /tmp/delete-dotnet.runtime.sh - when: destroy - dotnet.runtime~software.application#tar.archive::terraform@*->remote.machine: - derived_from: dotnet.runtime - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-dotnet.runtime - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-dotnet.runtime {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-dotnet.runtime -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-dotnet.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-dotnet.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-dotnet.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-dotnet.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-dotnet.runtime.sh - remote-exec: - - inline: - - sudo bash /tmp/create-dotnet.runtime.sh - - sudo bash /tmp/configure-dotnet.runtime.sh - - sudo bash /tmp/start-dotnet.runtime.sh - - inline: - - sudo bash /tmp/stop-dotnet.runtime.sh - - sudo bash /tmp/delete-dotnet.runtime.sh - when: destroy - dotnet.runtime~software.application#zip.archive::terraform@*->remote.machine: - derived_from: dotnet.runtime - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-dotnet.runtime - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-dotnet.runtime {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-dotnet.runtime -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-dotnet.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-dotnet.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-dotnet.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-dotnet.runtime.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-dotnet.runtime.sh - remote-exec: - - inline: - - sudo bash /tmp/create-dotnet.runtime.sh - - sudo bash /tmp/configure-dotnet.runtime.sh - - sudo bash /tmp/start-dotnet.runtime.sh - - inline: - - sudo bash /tmp/stop-dotnet.runtime.sh - - sudo bash /tmp/delete-dotnet.runtime.sh - when: destroy - gcp.cloudrun~gcp.service::ansible: - derived_from: gcp.cloudrun - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: - - name: enable service - google.cloud.gcp_serviceusage_service: - name: '{{ SELF.gcp_service }}' - project: '{{ SELF.gcp_project }}' - delete: exit 0 - gcp.cloudrun~gcp.service::terraform: - derived_from: gcp.cloudrun - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 4.67.0 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - resource: - google_project_service: - cloud_sql_admin: - - disable_on_destroy: false - project: '{{ SELF.gcp_project }}' - service: '{{ SELF.gcp_service }}' - gcp.cloudsql~gcp.service::ansible: - derived_from: gcp.cloudsql - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: - - name: enable service - google.cloud.gcp_serviceusage_service: - name: '{{ SELF.gcp_service }}' - project: '{{ SELF.gcp_project }}' - delete: exit 0 - gcp.cloudsql~gcp.service::terraform: - derived_from: gcp.cloudsql - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 4.67.0 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - resource: - google_project_service: - cloud_sql_admin: - - disable_on_destroy: false - project: '{{ SELF.gcp_project }}' - service: '{{ SELF.gcp_service }}' - gcp.appengine~gcp.service::ansible: - derived_from: gcp.appengine - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: - - name: enable service - google.cloud.gcp_serviceusage_service: - name: '{{ SELF.gcp_service }}' - project: '{{ SELF.gcp_project }}' - delete: exit 0 - gcp.appengine~gcp.service::terraform: - derived_from: gcp.appengine - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 4.67.0 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - resource: - google_project_service: - cloud_sql_admin: - - disable_on_destroy: false - project: '{{ SELF.gcp_project }}' - service: '{{ SELF.gcp_service }}' - gcp.appenginereporting~gcp.service::ansible: - derived_from: gcp.appenginereporting - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: - - name: enable service - google.cloud.gcp_serviceusage_service: - name: '{{ SELF.gcp_service }}' - project: '{{ SELF.gcp_project }}' - delete: exit 0 - gcp.appenginereporting~gcp.service::terraform: - derived_from: gcp.appenginereporting - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 4.67.0 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - resource: - google_project_service: - cloud_sql_admin: - - disable_on_destroy: false - project: '{{ SELF.gcp_project }}' - service: '{{ SELF.gcp_service }}' - gcp.cloudbuild~gcp.service::ansible: - derived_from: gcp.cloudbuild - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: - - name: enable service - google.cloud.gcp_serviceusage_service: - name: '{{ SELF.gcp_service }}' - project: '{{ SELF.gcp_project }}' - delete: exit 0 - gcp.cloudbuild~gcp.service::terraform: - derived_from: gcp.cloudbuild - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 4.67.0 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - resource: - google_project_service: - cloud_sql_admin: - - disable_on_destroy: false - project: '{{ SELF.gcp_project }}' - service: '{{ SELF.gcp_service }}' - gcp.kubernetesengine~gcp.service::ansible: - derived_from: gcp.kubernetesengine - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: - - name: enable service - google.cloud.gcp_serviceusage_service: - name: '{{ SELF.gcp_service }}' - project: '{{ SELF.gcp_project }}' - delete: exit 0 - gcp.kubernetesengine~gcp.service::terraform: - derived_from: gcp.kubernetesengine - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 4.67.0 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - resource: - google_project_service: - cloud_sql_admin: - - disable_on_destroy: false - project: '{{ SELF.gcp_project }}' - service: '{{ SELF.gcp_service }}' - gcp.cloudstorage~gcp.service::ansible: - derived_from: gcp.cloudstorage - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: - - name: enable service - google.cloud.gcp_serviceusage_service: - name: '{{ SELF.gcp_service }}' - project: '{{ SELF.gcp_project }}' - delete: exit 0 - gcp.cloudstorage~gcp.service::terraform: - derived_from: gcp.cloudstorage - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 4.67.0 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - resource: - google_project_service: - cloud_sql_admin: - - disable_on_destroy: false - project: '{{ SELF.gcp_project }}' - service: '{{ SELF.gcp_service }}' - gcp.memorystore~gcp.service::ansible: - derived_from: gcp.memorystore - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: - - name: enable service - google.cloud.gcp_serviceusage_service: - name: '{{ SELF.gcp_service }}' - project: '{{ SELF.gcp_project }}' - delete: exit 0 - gcp.memorystore~gcp.service::terraform: - derived_from: gcp.memorystore - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 4.67.0 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - resource: - google_project_service: - cloud_sql_admin: - - disable_on_destroy: false - project: '{{ SELF.gcp_project }}' - service: '{{ SELF.gcp_service }}' - docker.engine~docker.engine::ansible@local.machine: - derived_from: docker.engine - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install docker - 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 - - name: add user to docker group - ansible.builtin.user: - name: '{{ SELF.os_ssh_user }}' - groups: docker - append: 'yes' - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - 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 - docker.engine~docker.engine::ansible@remote.machine: - derived_from: docker.engine - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install docker - 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 - - name: add user to docker group - ansible.builtin.user: - name: '{{ SELF.os_ssh_user }}' - groups: docker - append: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - docker.engine~software.application#tar.archive::ansible@*->remote.machine: - derived_from: docker.engine - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: |- - APPLICATION_NAME="{{ SELF.application_name }}" - _HOSTING="{{ SELF._hosting }}" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - docker.engine~software.application#zip.archive::ansible@*->remote.machine: - derived_from: docker.engine - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: |- - APPLICATION_NAME="{{ SELF.application_name }}" - _HOSTING="{{ SELF._hosting }}" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - docker.engine~docker.engine::terraform@local.machine: - derived_from: docker.engine - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - mysql: - source: hashicorp/local - version: 2.5.1 - provider: - local: - - endpoint: 127.0.0.1:{{ HOST.management_port }} - password: '{{ HOST.dbms_password }}' - username: root - resource: - local_file: - tmp_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 - # 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 - filename: /tmp/docker.service - terraform_data: - docker: - - depends_on: local_file.tmp_service - provisioner: - local-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~docker.engine::terraform@remote.machine: - derived_from: docker.engine - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - docker: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - 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: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - _HOSTING="{{ SELF._hosting }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-docker.engine {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-docker.engine.sh - remote-exec: - - inline: - - sudo bash /tmp/create-docker.engine.sh - - sudo bash /tmp/configure-docker.engine.sh - - sudo bash /tmp/start-docker.engine.sh - - inline: - - sudo bash /tmp/stop-docker.engine.sh - - sudo bash /tmp/delete-docker.engine.sh - when: destroy - docker.engine~software.application#tar.archive::terraform@*->remote.machine: - derived_from: docker.engine - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-docker.engine - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - _HOSTING="{{ SELF._hosting }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-docker.engine {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-docker.engine -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-docker.engine.sh - remote-exec: - - inline: - - sudo bash /tmp/create-docker.engine.sh - - sudo bash /tmp/configure-docker.engine.sh - - sudo bash /tmp/start-docker.engine.sh - - inline: - - sudo bash /tmp/stop-docker.engine.sh - - sudo bash /tmp/delete-docker.engine.sh - when: destroy - docker.engine~software.application#zip.archive::terraform@*->remote.machine: - derived_from: docker.engine - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-docker.engine - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - APPLICATION_NAME="{{ SELF.application_name }}" - _HOSTING="{{ SELF._hosting }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-docker.engine {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-docker.engine -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-docker.engine.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-docker.engine.sh - remote-exec: - - inline: - - sudo bash /tmp/create-docker.engine.sh - - sudo bash /tmp/configure-docker.engine.sh - - sudo bash /tmp/start-docker.engine.sh - - inline: - - sudo bash /tmp/stop-docker.engine.sh - - sudo bash /tmp/delete-docker.engine.sh - when: destroy - mysql.dbms~mysql.dbms#dbms.image::ansible@docker.engine->local.machine: - derived_from: mysql.dbms - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - application_port: - type: string - default: 3306 - management_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - management_port: - type: integer - default: 3306 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: start container - community.docker.docker_container: - name: '{{ SELF.dbms_name }}' - image: mysql:{{ ".artifacts::dbms_image::file" | eval }} - network_mode: host - env: - MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password | string }}' - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: delete container - community.docker.docker_container: - name: '{{ SELF.dbms_name }}' - state: absent - mysql.dbms~mysql.dbms#dbms.image::ansible@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: - type: string - default: - get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: 127.0.0.1 - application_port: - type: string - default: 3306 - management_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - management_port: - type: integer - default: 3306 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: start container - community.docker.docker_container: - name: '{{ SELF.dbms_name }}' - image: mysql:{{ ".artifacts::dbms_image::file" | eval }} - network_mode: host - env: - MYSQL_ROOT_PASSWORD: '{{ SELF.dbms_password | string }}' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - dbms_ssl_mode: - type: string - default: Preferred - attributes: - application_port: - type: string - default: 3306 - management_address: - type: string - default: - eval: .::application_address - management_port: - type: integer - default: - eval: .::application_port - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: - - name: create a instance - register: instance_info - google.cloud.gcp_sql_instance: - name: '{{ SELF.dbms_name }}' - database_version: MYSQL_{{ ".artifacts::dbms_image::file" | eval | replace(".", "_") }} - settings: - tier: db-f1-micro - availability_type: REGIONAL - backup_configuration: - binary_log_enabled: true - enabled: true - ip_configuration: - authorized_networks: - - value: 0.0.0.0/0 - region: '{{ SELF.gcp_region }}' - project: '{{ SELF.gcp_project }}' - - name: set root password - google.cloud.gcp_sql_user: - name: root - host: '%' - password: '{{ SELF.dbms_password }}' - instance: '{{ instance_info }}' - project: '{{ SELF.gcp_project }}' - - name: aet attributes - set_fact: - application_address: '{{ instance_info.ipAddresses[0].ipAddress | trim }}' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address }}' - outputs: - application_address: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: Activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: Delete Instance - ansible.builtin.shell: gcloud sql instances delete {{ SELF.dbms_name }} --quiet - args: - executable: /bin/bash - mysql.dbms~mysql.dbms#dbms.image::ansible@kubernetes.cluster: - derived_from: mysql.dbms - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::dbms_name - application_port: - type: integer - default: 3306 - management_address: - type: string - default: - eval: .::application_address - management_port: - type: integer - default: - eval: .::application_port - interfaces: - Standard: - operations: - create: - 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: create deployment - kubernetes.core.k8s: - wait: true - definition: - 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 - - name: create service - kubernetes.core.k8s: - definition: - apiVersion: v1 - kind: Service - metadata: - name: '{{ SELF.dbms_name }}' - namespace: default - spec: - ports: - - name: mysql - port: 3306 - targetPort: 3306 - selector: - app: '{{ SELF.dbms_name }}' - type: ClusterIP - 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: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_port: - type: string - default: 3001 - application_address: - type: string - default: 127.0.0.1 - attributes: - management_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - management_port: - type: integer - default: - eval: .::application_port - capabilities: - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: installing mysql - ansible.builtin.apt: - name: - - mysql-server - - mysql-client - - python3-mysqldb - - libmysqlclient-dev - state: present - update_cache: 'yes' - - name: start and enable mysql service - ansible.builtin.systemd: - name: mysql - state: started - enabled: 'yes' - - name: enable passwordless login - ansible.builtin.copy: - dest: '{{ item }}' - content: | - [client] - user=root - password={{ SELF.dbms_password }} - loop: - - /root/.my.cnf - - /home/{{ SELF.os_ssh_user }}/.my.cnf - - 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 - 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 - ansible.builtin.systemd: - name: mysql - state: restarted - - name: create all root - community.mysql.mysql_user: - name: root - password: '{{ SELF.dbms_password }}' - priv: '*.*:ALL' - host: '%' - state: present - login_host: localhost - login_password: '{{ SELF.dbms_password }}' - login_port: '{{ SELF.application_port }}' - login_user: root - - name: delete localhost root - community.mysql.mysql_user: - name: root - host: localhost - state: absent - login_host: localhost - login_password: '{{ SELF.dbms_password }}' - login_port: '{{ SELF.application_port }}' - login_user: root - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - mysql.dbms~software.application#tar.archive::ansible@*->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: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: |- - DBMS_NAME="{{ SELF.dbms_name }}" - APPLICATION_NAME="{{ SELF.application_name }}" - DBMS_PASSWORD="{{ SELF.dbms_password }}" - DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - mysql.dbms~software.application#zip.archive::ansible@*->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: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: |- - DBMS_NAME="{{ SELF.dbms_name }}" - APPLICATION_NAME="{{ SELF.application_name }}" - DBMS_PASSWORD="{{ SELF.dbms_password }}" - DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - mysql.dbms~mysql.dbms#dbms.image::terraform@docker.engine->local.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: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - application_port: - type: integer - default: 3306 - management_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - management_port: - type: integer - default: 3306 - capabilities: - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: unix:///var/run/docker.sock - resource: - docker_container: - application: - - name: '{{ SELF.dbms_name }}' - image: ${docker_image.image.image_id} - network_mode: host - env: - - MYSQL_ROOT_PASSWORD={{ SELF.dbms_password }} - docker_image: - image: - - name: mysql:{{ ".artifacts::dbms_image::file" | eval }} - mysql.dbms~mysql.dbms#dbms.image::terraform@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: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - application_port: - type: integer - default: 3306 - management_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - management_port: - type: integer - default: 3306 - capabilities: - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 - ssh_opts: - - '-i' - - '{{ SELF.os_ssh_key_file }}' - - '-o' - - IdentitiesOnly=yes - - '-o' - - BatchMode=yes - - '-o' - - UserKnownHostsFile=/dev/null - - '-o' - - StrictHostKeyChecking=no - resource: - docker_container: - application: - - name: '{{ SELF.dbms_name }}' - image: ${docker_image.image.image_id} - network_mode: host - env: - - MYSQL_ROOT_PASSWORD={{ SELF.dbms_password }} - docker_image: - image: - - name: mysql:{{ ".artifacts::dbms_image::file" | eval }} - mysql.dbms~mysql.dbms#dbms.image::terraform@gcp.cloudsql: - derived_from: mysql.dbms - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - dbms_ssl_mode: - type: string - default: Preferred - attributes: - application_port: - type: string - default: 3306 - management_address: - type: string - default: - eval: .::application_address - management_port: - type: integer - default: - eval: .::application_port - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 4.67.0 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: ${google_sql_database_instance.dbms.public_ip_address} - resource: - google_sql_database_instance: - dbms: - - database_version: MYSQL_{{ ".artifacts::dbms_image::file" | eval | replace(".", "_") }} - deletion_protection: false - name: '{{ SELF.dbms_name }}' - root_password: '{{ SELF.dbms_password }}' - settings: - - availability_type: REGIONAL - backup_configuration: - - binary_log_enabled: true - enabled: true - ip_configuration: - - authorized_networks: - - name: public - value: 0.0.0.0/0 - ipv4_enabled: true - tier: db-f1-micro - google_sql_user: - user: - - host: '%' - instance: ${google_sql_database_instance.dbms.name} - name: root - password: ${google_sql_database_instance.dbms.root_password} - mysql.dbms~mysql.dbms#dbms.image::terraform@kubernetes.cluster: - derived_from: mysql.dbms - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::dbms_name - application_port: - type: integer - default: 3306 - management_address: - type: string - default: - eval: .::application_address - management_port: - type: integer - default: - eval: .::application_port - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - kubernetes: - source: hashicorp/kubernetes - version: 2.31.0 - required_version: '>= 0.14.0' - provider: - kubernetes: - - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} - client_key: ${file("{{ SELF.k8s_client_key_file }}")} - cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} - host: '{{ SELF.k8s_host }}' - resource: - kubernetes_deployment_v1: - application: - - metadata: - - name: '{{ SELF.dbms_name }}' - spec: - - selector: - - match_labels: - app: '{{ SELF.dbms_name }}' - template: - - metadata: - - labels: - app: '{{ SELF.dbms_name }}' - spec: - - container: - - name: '{{ SELF.dbms_name }}' - image: mysql:{{ ".artifacts::dbms_image::file" | eval }} - env: - - name: MYSQL_ROOT_PASSWORD - value: '{{ SELF.dbms_password }}' - port: - - container_port: 3306 - name: mysql - kubernetes_service_v1: - application: - - metadata: - - name: '{{ SELF.dbms_name }}' - spec: - - port: - - name: mysql - port: 3306 - target_port: 3306 - selector: - app: '{{ SELF.dbms_name }}' - type: ClusterIP - mysql.dbms~mysql.dbms#dbms.image::terraform@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: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_port: - type: string - default: 3001 - application_address: - type: string - default: 127.0.0.1 - attributes: - management_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - management_port: - type: integer - default: - eval: .::application_port - capabilities: - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - - #!/usr/bin/bash - set -e - export DEBIAN_FRONTEND="noninteractive" - - DBMS_PASSWORD=$1 - DBMS_PORT=$2 - - # Set password - debconf-set-selections <<< "mysql-server mysql-server/root_password password ${DBMS_PASSWORD}" - debconf-set-selections <<< "mysql-server mysql-server/root_password_again password ${DBMS_PASSWORD}" - - # Install mysql - apt-get update -y - apt-get -y install mysql-server - - # Passwordless auth - cat < /root/.my.cnf - [client] - user=root - password=${DBMS_PASSWORD} - EOF - - # Listen on all interfaces - sed -i "s/127\.0\.0\.1/0\.0\.0\.0/g" /etc/mysql/mysql.conf.d/mysqld.cnf - - # Listen on custom port - sed -i "s/# port.*/port = ${DBMS_PORT}/g" /etc/mysql/mysql.conf.d/mysqld.cnf - - # Configure any host for root - mysql -u root -e 'USE mysql; UPDATE user SET host = "%" WHERE user = "root"; FLUSH PRIVILEGES;' - mysql -u root -e 'USE mysql; DELETE FROM user WHERE user = "root" and host = "localhost"; FLUSH PRIVILEGES;' - - # Enable service - systemctl enable mysql - - # Restart service - systemctl restart mysql - destination: /tmp/install-mysql-dbms.sh - remote-exec: - - inline: - - sudo bash /tmp/install-mysql-dbms.sh {{ SELF.dbms_password }} {{ SELF.application_port }} - mysql.dbms~software.application#apt.archive::terraform@*->remote.machine: - derived_from: mysql.dbms - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - DBMS_NAME="{{ SELF.dbms_name }}" - APPLICATION_NAME="{{ SELF.application_name }}" - DBMS_PASSWORD="{{ SELF.dbms_password }}" - DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-mysql.dbms {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-mysql.dbms.sh - remote-exec: - - inline: - - sudo bash /tmp/create-mysql.dbms.sh - - sudo bash /tmp/configure-mysql.dbms.sh - - sudo bash /tmp/start-mysql.dbms.sh - - inline: - - sudo bash /tmp/stop-mysql.dbms.sh - - sudo bash /tmp/delete-mysql.dbms.sh - when: destroy - mysql.dbms~software.application#tar.archive::terraform@*->remote.machine: - derived_from: mysql.dbms - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-mysql.dbms - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - DBMS_NAME="{{ SELF.dbms_name }}" - APPLICATION_NAME="{{ SELF.application_name }}" - DBMS_PASSWORD="{{ SELF.dbms_password }}" - DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-mysql.dbms {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-mysql.dbms -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-mysql.dbms.sh - remote-exec: - - inline: - - sudo bash /tmp/create-mysql.dbms.sh - - sudo bash /tmp/configure-mysql.dbms.sh - - sudo bash /tmp/start-mysql.dbms.sh - - inline: - - sudo bash /tmp/stop-mysql.dbms.sh - - sudo bash /tmp/delete-mysql.dbms.sh - when: destroy - mysql.dbms~software.application#zip.archive::terraform@*->remote.machine: - derived_from: mysql.dbms - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-mysql.dbms - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - DBMS_NAME="{{ SELF.dbms_name }}" - APPLICATION_NAME="{{ SELF.application_name }}" - DBMS_PASSWORD="{{ SELF.dbms_password }}" - DBMS_SSL_MODE="{{ SELF.dbms_ssl_mode }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-mysql.dbms {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-mysql.dbms -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-mysql.dbms.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-mysql.dbms.sh - remote-exec: - - inline: - - sudo bash /tmp/create-mysql.dbms.sh - - sudo bash /tmp/configure-mysql.dbms.sh - - sudo bash /tmp/start-mysql.dbms.sh - - inline: - - sudo bash /tmp/stop-mysql.dbms.sh - - sudo bash /tmp/delete-mysql.dbms.sh - when: destroy - mysql.dbms~mysql.dbms#dbms.image::kubernetes@kubernetes.cluster: - derived_from: mysql.dbms - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::dbms_name - application_port: - type: integer - default: 3306 - management_address: - type: string - default: - eval: .::application_address - management_port: - type: integer - default: - eval: .::application_port - interfaces: - Standard: - operations: - create: - 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: 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 }} rollout status deployment/{{ SELF.dbms_name }} --timeout 60s - args: - executable: /usr/bin/bash - - name: let it cook - ansible.builtin.pause: - seconds: 10 - 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->local.machine: - derived_from: mysql.dbms - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - application_port: - type: integer - default: 3306 - management_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - management_port: - type: integer - default: 3306 - capabilities: - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address - interfaces: - Standard: - operations: - create: - 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: apply compose - ansible.builtin.shell: docker compose -f {{ compose.path }} up -d - args: - executable: /usr/bin/bash - - name: let it cook - ansible.builtin.pause: - seconds: 10 - 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 - 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_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - application_port: - type: integer - default: 3306 - management_address: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - management_port: - type: integer - default: 3306 - capabilities: - endpoint: - type: unfurl.capabilities.Endpoint.Ansible - properties: - connection: ssh - host: - eval: .parent::management_address - interfaces: - Standard: - operations: - create: - 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: 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: let it cook - ansible.builtin.pause: - seconds: 10 - 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->local.machine: - derived_from: mysql.database - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: get dbms container info - community.docker.docker_container_info: - name: '{{ HOST.dbms_name }}' - register: dbms_container_info - - 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 - - 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 - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - 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 - mysql.database~mysql.database::ansible@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: - type: string - default: - get_input: os_ssh_key_file - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install pip - apt: - name: python3-pip - state: present - - name: install pymysql - pip: - name: pymysql - state: present - - name: get dbms container info - community.docker.docker_container_info: - name: '{{ HOST.dbms_name }}' - register: dbms_container_info - - name: forward port - community.docker.docker_container: - name: '{{ HOST.dbms_name }}-port-forward' - image: nicolaka/netshoot:v0.13 - command: socat TCP6-LISTEN:3306,fork TCP:{{ HOST.dbms_name }}:3306 - ports: - - '{{ HOST.application_port }}:3306' - when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" - - name: create forwarding network - community.docker.docker_network: - name: '{{ HOST.dbms_name }}-port-forward' - connected: - - '{{ HOST.dbms_name }}-port-forward' - - '{{ HOST.dbms_name }}' - when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" - - 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 - - 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 - - name: unforward port - community.docker.docker_container: - name: '{{ HOST.dbms_name }}-port-forward' - image: nicolaka/netshoot:v0.13 - network_mode: host - state: absent - when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" - - name: remove forwarding network - community.docker.docker_network: - name: '{{ HOST.dbms_name }}-port-forward' - state: absent - when: "'host' not in dbms_container_info.container.NetworkSettings.Networks" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - environment: - GCP_SERVICE_ACCOUNT_FILE: - eval: .::gcp_service_account_file - GCP_AUTH_KIND: serviceaccount - inputs: - playbook: - q: - - name: create a database - google.cloud.gcp_sql_database: - name: '{{ SELF.database_name }}' - charset: utf8 - instance: '{{ HOST.dbms_name }}' - project: '{{ SELF.gcp_project }}' - - name: install GCP CloudSQL Proxy - ansible.builtin.get_url: - url: https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.13.0/cloud-sql-proxy.linux.amd64 - dest: /tmp/gcp-cloudsql-proxy - mode: '0755' - - name: forward port - ansible.builtin.shell: '/tmp/gcp-cloudsql-proxy {{ SELF.gcp_project }}:{{ SELF.gcp_region }}:{{ HOST.dbms_name }} --credentials-file {{ SELF.gcp_service_account_file }} --port 23306 ' - args: - executable: /usr/bin/bash - async: 30 - poll: 0 - - name: wait for port - ansible.builtin.wait_for: - host: 127.0.0.1 - port: 23306 - delay: 5 - timeout: 30 - - name: create user (with privileges) - community.mysql.mysql_user: - name: '{{ SELF.database_user }}' - password: '{{ SELF.database_password }}' - host: '%' - priv: '*.*:ALL' - login_host: 127.0.0.1 - login_password: '{{ HOST.dbms_password }}' - login_port: 23306 - login_user: root - - name: unforward port - ansible.builtin.shell: pkill -f "/tmp/gcp-cloudsql-proxy {{ SELF.gcp_project }}:{{ SELF.gcp_region }}:{{ HOST.dbms_name }}" - args: - executable: /usr/bin/bash - mysql.database~mysql.database::ansible@mysql.dbms->kubernetes.cluster: - derived_from: mysql.database - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: deploy database - block: - - name: forward port - 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 - poll: 0 - - name: wait for port - ansible.builtin.wait_for: - host: 127.0.0.1 - port: 23306 - delay: 5 - timeout: 30 - - name: create database - community.mysql.mysql_db: - name: '{{ SELF.database_name }}' - login_host: 127.0.0.1 - login_password: '{{ HOST.dbms_password }}' - login_port: '23306' - login_user: root - - name: create user (with privileges) - community.mysql.mysql_user: - name: '{{ SELF.database_user }}' - password: '{{ SELF.database_password }}' - host: '%' - priv: '*.*:ALL' - login_host: 127.0.0.1 - login_password: '{{ HOST.dbms_password }}' - login_port: '23306' - login_user: root - always: - - name: unforward port - 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: - 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: - type: string - default: - get_input: os_ssh_key_file - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install pip - apt: - name: python3-pip - state: present - - name: install pymysql - pip: - name: pymysql - state: present - - 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 - - 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 - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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->local.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: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - mysql: - source: petoju/mysql - version: 3.0.48 - provider: - mysql: - - endpoint: 127.0.0.1:{{ HOST.management_port }} - password: '{{ HOST.dbms_password }}' - username: root - resource: - mysql_database: - database: - - name: '{{ SELF.database_name }}' - mysql_user: - user: - - host: '%' - plaintext_password: '{{ SELF.database_password }}' - user: '{{ SELF.database_user }}' - mysql_grant: - user: - - database: '{{ SELF.database_name }}' - host: '%' - table: '*' - privileges: - - ALL - user: ${mysql_user.user.user} - mysql.database~mysql.database::terraform@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: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - mysql: - source: petoju/mysql - version: 3.0.48 - ssh: - source: AndrewChubatiuk/ssh - version: 0.2.3 - data: - ssh_tunnel: - mysql: - - remote: - host: '{{ HOST.application_address }}' - port: '{{ HOST.application_port }}' - provider: - mysql: - - endpoint: ${data.ssh_tunnel.mysql.local.address} - password: '{{ HOST.dbms_password }}' - username: root - ssh: - - auth: - private_key: - content: ${file(pathexpand("{{ SELF.os_ssh_key_file }}"))} - server: - host: '{{ HOST.management_address }}' - port: 22 - user: '{{ SELF.os_ssh_user }}' - resource: - mysql_database: - database: - - name: '{{ SELF.database_name }}' - mysql_user: - user: - - host: '%' - plaintext_password: '{{ SELF.database_password }}' - user: '{{ SELF.database_user }}' - mysql_grant: - user: - - database: '{{ SELF.database_name }}' - host: '%' - table: '*' - privileges: - - ALL - user: ${mysql_user.user.user} - mysql.database~mysql.database::terraform@mysql.dbms->gcp.cloudsql: - derived_from: mysql.database - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - environment: - GOOGLE_APPLICATION_CREDENTIALS: - eval: .::gcp_service_account_file - delete: - implementation: - primary: Terraform - environment: - GOOGLE_APPLICATION_CREDENTIALS: - eval: .::gcp_service_account_file - defaults: - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - mysql: - source: petoju/mysql - version: 3.0.48 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - mysql: - - endpoint: cloudsql://{{ SELF.gcp_project }}:{{ SELF.gcp_region }}:{{ HOST.dbms_name }} - password: '{{ HOST.dbms_password }}' - username: root - resource: - google_sql_database: - database: - - name: '{{ SELF.database_name }}' - instance: '{{ HOST.dbms_name }}' - google_sql_user: - user: - - host: '%' - instance: '{{ HOST.dbms_name }}' - name: '{{ SELF.database_name }}' - password: '{{ SELF.database_password }}' - mysql_grant: - user: - - database: '{{ SELF.database_name }}' - host: '%' - table: '*' - privileges: - - ALL - user: ${google_sql_user.user.name} - mysql.database~mysql.database::terraform@mysql.dbms->kubernetes.cluster: - derived_from: mysql.database - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - mysql: - source: petoju/mysql - version: 3.0.48 - provider: - mysql: - - endpoint: ${terraform_data.forward_port.input} - password: '{{ HOST.dbms_password }}' - username: root - resource: - terraform_data: - forward_port: - - input: 127.0.0.1:23306 - provisioner: - local-exec: - command: |- - (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 - - '-c' - unforward_port: - - depends_on: - - mysql_grant.user - provisioner: - local-exec: - command: pkill -f "port-forward service/{{ HOST.dbms_name }}" - interpreter: - - /bin/bash - - '-c' - mysql_database: - database: - - name: '{{ SELF.database_name }}' - mysql_user: - user: - - host: '%' - plaintext_password: '{{ SELF.database_password }}' - user: '{{ SELF.database_user }}' - mysql_grant: - user: - - database: '{{ SELF.database_name }}' - host: '%' - table: '*' - privileges: - - ALL - user: ${mysql_user.user.user} - mysql.database~mysql.database::terraform@mysql.dbms->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: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - mysql: - source: petoju/mysql - version: 3.0.48 - ssh: - source: AndrewChubatiuk/ssh - version: 0.2.3 - data: - ssh_tunnel: - mysql: - - remote: - host: '{{ HOST.application_address }}' - port: '{{ HOST.application_port }}' - provider: - mysql: - - endpoint: ${data.ssh_tunnel.mysql.local.address} - password: '{{ HOST.dbms_password }}' - username: root - ssh: - - auth: - private_key: - content: ${file(pathexpand("{{ SELF.os_ssh_key_file }}"))} - server: - host: '{{ HOST.management_address }}' - port: 22 - user: '{{ SELF.os_ssh_user }}' - resource: - mysql_database: - database: - - name: '{{ SELF.database_name }}' - mysql_user: - user: - - host: '%' - plaintext_password: '{{ SELF.database_password }}' - user: '{{ SELF.database_user }}' - mysql_grant: - user: - - database: '{{ SELF.database_name }}' - host: '%' - table: '*' - privileges: - - ALL - user: ${mysql_user.user.user} - mysql.database~mysql.database::kubernetes@mysql.dbms->kubernetes.cluster: - derived_from: mysql.database - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - interfaces: - Standard: - operations: - create: - 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 - - '--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 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 - - '--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 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 - mysql.database~mysql.database::compose@mysql.dbms->docker.engine->local.machine: - derived_from: mysql.database - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - interfaces: - Standard: - operations: - create: - 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' - - 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 - 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 - - 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 - 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_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - interfaces: - Standard: - operations: - create: - 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' - - 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 - 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 }}' - 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 }}' - minio.server~service.application#docker.image::ansible@docker.engine->local.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: stop container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - state: absent - minio.server~service.application#docker.image::ansible@docker.engine->remote.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: {} - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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 }}' - minio.server~service.application#docker.image::ansible@gcp.cloudrun: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: touch service - register: service - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.service.yaml' - - name: create service - ansible.builtin.copy: - dest: '{{ service.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - apiVersion: serving.knative.dev/v1 - kind: Service - metadata: - name: '{{ SELF.application_name }}' - labels: - cloud.googleapis.com/location: '{{ SELF.gcp_region }}' - annotations: - run.googleapis.com/ingress: all - spec: - template: - spec: - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - containerPort: '{{ SELF.application_port }}' - env: [] - - name: apply service - ansible.builtin.shell: gcloud run services replace {{ service.path }} --quiet - args: - executable: /bin/bash - - name: touch policy - register: policy - ansible.builtin.tempfile: - suffix: '{{ SELF.application_name }}.policy.yaml' - - name: fill policy - ansible.builtin.copy: - dest: '{{ policy.path }}' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - bindings: - - members: - - allUsers - role: roles/run.invoker - - name: apply policy - ansible.builtin.shell: gcloud run services set-iam-policy {{ SELF.application_name }} {{ policy.path }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - - name: describe service - register: service_description - ansible.builtin.shell: gcloud run services describe {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet --format=json - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ (service_description.stdout | from_json ).status.url[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ (service_description.stdout | from_json ).status.url[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud run services delete {{ SELF.application_name }} --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - minio.server~service.application#docker.image::ansible@kubernetes.cluster: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: create deployment - kubernetes.core.k8s: - wait: true - definition: - 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 }}' - - name: create service - kubernetes.core.k8s: - definition: - 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 - 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 }}' - minio.server~service.application#tar.archive::ansible@*->remote.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - minio.server~service.application#zip.archive::ansible@*->remote.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: create service - ansible.builtin.copy: - dest: /etc/systemd/system/{{ SELF.application_name }}.service - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - - name: enable service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: start service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: started - enabled: 'yes' - daemon_reload: 'yes' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: stop service - ansible.builtin.systemd: - name: '{{ SELF.application_name }}' - state: stopped - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete systemd service - ansible.builtin.file: - path: /etc/systemd/system/{{ SELF.application_name }}.service - state: absent - - name: reload daemon - ansible.builtin.systemd: - daemon_reload: true - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - minio.server~service.application#zip.archive::ansible@gcp.appengine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: enable GCP AppEngine - ansible.builtin.shell: gcloud app create --region {{ SELF.gcp_region }} --quiet - args: - executable: /bin/bash - register: app_create_command - failed_when: - - "'Created' not in app_create_command.stderr" - - "'already contains' not in app_create_command.stderr" - - name: create working directory - register: directory - ansible.builtin.tempfile: - state: directory - - name: extract deployment artifact in working directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ directory.path }}' - - name: create specification - ansible.builtin.copy: - dest: '{{ directory.path }}/app.yaml' - content: '{{ manifest | to_yaml }}' - vars: - manifest: - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - instance_class: F1 - env_variables: {} - - name: create app - ansible.builtin.shell: gcloud app deploy {{ directory.path }} --quiet - args: - executable: /bin/bash - - name: browse app - register: browse_app - ansible.builtin.shell: 'gcloud app browse --service {{ SELF.application_name }} --no-launch-browser --quiet ' - args: - executable: /bin/bash - - name: set attributes - set_fact: - application_address: '{{ browse_app.stdout[8:] | trim }}' - application_endpoint: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ browse_app.stdout[8:] | trim }}:443' - resultTemplate: | - name: SELF - attributes: - application_address: '{{ outputs.application_address | trim }}' - application_endpoint: '{{ outputs.application_endpoint | trim }}' - outputs: - application_address: - application_endpoint: - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: activate service account - ansible.builtin.shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} - args: - executable: /bin/bash - - name: delete app - ansible.builtin.shell: gcloud app services delete {{ SELF.application_name }} --quiet - args: - executable: /bin/bash - minio.server~software.application#apt.package::ansible@*->remote.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - minio.server~software.application#tar.archive::ansible@*->remote.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - minio.server~software.application#zip.archive::ansible@*->remote.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: '' - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - minio.server~service.application#docker.image::terraform@docker.engine->local.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: unix:///var/run/docker.sock - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - minio.server~service.application#docker.image::terraform@docker.engine->remote.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 - ssh_opts: - - '-i' - - '{{ SELF.os_ssh_key_file }}' - - '-o' - - IdentitiesOnly=yes - - '-o' - - BatchMode=yes - - '-o' - - UserKnownHostsFile=/dev/null - - '-o' - - StrictHostKeyChecking=no - resource: - docker_container: - application: - - env: [] - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - minio.server~service.application#docker.image::terraform@gcp.cloudrun: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: ${substr(google_cloud_run_v2_service.application.uri, 8, -1)} - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://${substr(google_cloud_run_v2_service.application.uri, 8, -1)}:443' - resource: - google_cloud_run_v2_service: - application: - - ingress: INGRESS_TRAFFIC_ALL - location: '{{ SELF.gcp_region }}' - name: '{{ SELF.application_name }}' - template: - - containers: - - image: '{{ ".artifacts::docker_image::file" | eval }}' - ports: - - name: http1 - container_port: '{{ SELF.application_port }}' - env: [] - google_cloud_run_service_iam_binding: - application: - - location: '{{ SELF.gcp_region }}' - members: - - allUsers - role: roles/run.invoker - service: '{{ SELF.application_name }}' - minio.server~service.application#docker.image::terraform@kubernetes.cluster: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - k8s_host: - type: string - default: - get_input: k8s_host - k8s_ca_cert_file: - type: string - default: - get_input: k8s_ca_cert_file - k8s_client_cert_file: - type: string - default: - get_input: k8s_client_cert_file - k8s_client_key_file: - type: string - default: - get_input: k8s_client_key_file - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - kubernetes: - source: hashicorp/kubernetes - version: 2.31.0 - required_version: '>= 0.14.0' - provider: - kubernetes: - - client_certificate: ${file("{{ SELF.k8s_client_cert_file }}")} - client_key: ${file("{{ SELF.k8s_client_key_file }}")} - cluster_ca_certificate: ${file("{{ SELF.k8s_ca_cert_file }}")} - host: '{{ SELF.k8s_host }}' - resource: - kubernetes_deployment_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - selector: - - match_labels: - app: '{{ SELF.application_name }}' - template: - - metadata: - - labels: - app: '{{ SELF.application_name }}' - spec: - - container: - - env: [] - image: '{{ ".artifacts::docker_image::file" | eval }}' - name: '{{ SELF.application_name }}' - port: - - container_port: '{{ SELF.application_port }}' - kubernetes_service_v1: - application: - - metadata: - - name: '{{ SELF.application_name }}' - spec: - - port: - - name: '{{ SELF.application_protocol }}' - port: '{{ SELF.application_port }}' - target_port: '{{ SELF.application_port }}' - selector: - app: '{{ SELF.application_name }}' - type: ClusterIP - minio.server~service.application#tar.archive::terraform@*->remote.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-minio.server - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-minio.server {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-minio.server -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-minio.server.sh - remote-exec: - - inline: - - sudo bash /tmp/create-minio.server.sh - - sudo bash /tmp/configure-minio.server.sh - - sudo bash /tmp/start-minio.server.sh - - inline: - - sudo bash /tmp/stop-minio.server.sh - - sudo bash /tmp/delete-minio.server.sh - when: destroy - minio.server~service.application#zip.archive::terraform@*->remote.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-minio.server - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - [Unit] - After=network.target - - [Service] - Type=simple - ExecStart=/usr/bin/bash -c ". ./.vintner/start.sh" - WorkingDirectory={{ SELF.application_directory }} - EnvironmentFile={{ SELF.application_directory }}/.env - - [Install] - WantedBy=multi-user.target - destination: /etc/systemd/system/{{ SELF.application_name }}.service - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-minio.server {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-minio.server -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Reload systemd daemon - systemctl daemon-reload - - # Enable service - systemctl enable {{ SELF.application_name }} - destination: /tmp/create-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Start service - systemctl start {{ SELF.application_name }} - destination: /tmp/start-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - - # Stop service - systemctl stop {{ SELF.application_name }} - destination: /tmp/stop-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Delete systemd service - rm -f /etc/systemd/system/{{ SELF.application_name }}.service - - # Reload system daemon - systemctl daemon-reload - destination: /tmp/delete-minio.server.sh - remote-exec: - - inline: - - sudo bash /tmp/create-minio.server.sh - - sudo bash /tmp/configure-minio.server.sh - - sudo bash /tmp/start-minio.server.sh - - inline: - - sudo bash /tmp/stop-minio.server.sh - - sudo bash /tmp/delete-minio.server.sh - when: destroy - minio.server~service.application#zip.archive::terraform@gcp.appengine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - outputs: - application_address: application_address - application_endpoint: application_endpoint - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - output: - application_address: - - value: '{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com' - application_endpoint: - - value: '{{ SELF.application_protocol if SELF.application_protocol.endswith("s") else SELF.application_protocol + "s" }}://{{ SELF.application_name }}-dot-{{ SELF.gcp_project }}.ey.r.appspot.com:443' - resource: - google_app_engine_standard_app_version: - app: - - delete_service_on_destroy: true - deployment: - - zip: - - source_url: https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name} - entrypoint: - - shell: '{{ SELF._management_start }}' - env_variables: {} - runtime: '{{ SELF.application_language }}' - service: '{{ SELF.application_name }}' - service_account: ${google_service_account.custom_service_account.email} - version_id: v1 - google_project_iam_member: - gae_api: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/compute.networkUser - storage_viewer: - - member: serviceAccount:${google_service_account.custom_service_account.email} - project: ${google_service_account.custom_service_account.project} - role: roles/storage.objectViewer - google_service_account: - custom_service_account: - - account_id: '{{ SELF.application_name }}-account' - display_name: Custom Service Account - google_storage_bucket: - bucket: - - location: EU - name: '{{ SELF.gcp_project }}-{{ SELF.application_name }}' - google_storage_bucket_object: - object: - - bucket: ${google_storage_bucket.bucket.name} - name: object.zip - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - minio.server~software.application#apt.archive::terraform@*->remote.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-minio.server {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-minio.server.sh - remote-exec: - - inline: - - sudo bash /tmp/create-minio.server.sh - - sudo bash /tmp/configure-minio.server.sh - - sudo bash /tmp/start-minio.server.sh - - inline: - - sudo bash /tmp/stop-minio.server.sh - - sudo bash /tmp/delete-minio.server.sh - when: destroy - minio.server~software.application#tar.archive::terraform@*->remote.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-minio.server - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-minio.server {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-minio.server -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-minio.server.sh - remote-exec: - - inline: - - sudo bash /tmp/create-minio.server.sh - - sudo bash /tmp/configure-minio.server.sh - - sudo bash /tmp/start-minio.server.sh - - inline: - - sudo bash /tmp/stop-minio.server.sh - - sudo bash /tmp/delete-minio.server.sh - when: destroy - minio.server~software.application#zip.archive::terraform@*->remote.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-minio.server - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-minio.server {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-minio.server -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-minio.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-minio.server.sh - remote-exec: - - inline: - - sudo bash /tmp/create-minio.server.sh - - sudo bash /tmp/configure-minio.server.sh - - sudo bash /tmp/start-minio.server.sh - - inline: - - sudo bash /tmp/stop-minio.server.sh - - sudo bash /tmp/delete-minio.server.sh - when: destroy - minio.server~service.application#docker.image::kubernetes@kubernetes.cluster: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: - eval: .::application_name - interfaces: - Standard: - operations: - create: - 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: 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 }} 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 - minio.server~service.application#docker.image::compose@docker.engine->local.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 - minio.server~service.application#docker.image::compose@docker.engine->remote.machine: - derived_from: minio.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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 }} up -d - args: - executable: /usr/bin/bash - 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 }}' - redis.server~redis.server#cache.image::ansible@docker.engine->local.machine: - derived_from: redis.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: - CACHE_NAME: '"{{ SELF.cache_name }}"' - CACHE_PORT: '"{{ SELF.cache_port }}"' - APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' - APPLICATION_NAME: '"{{ SELF.application_name }}"' - APPLICATION_PORT: '"{{ SELF.application_port }}"' - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: - - name: stop container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - state: absent - redis.server~redis.server#cache.image::ansible@docker.engine->remote.machine: - derived_from: redis.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: start container - community.docker.docker_container: - name: '{{ SELF.application_name }}' - image: '{{ ".artifacts::docker_image::file" | eval }}' - network_mode: host - env: - CACHE_NAME: '"{{ SELF.cache_name }}"' - CACHE_PORT: '"{{ SELF.cache_port }}"' - APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' - APPLICATION_NAME: '"{{ SELF.application_name }}"' - APPLICATION_PORT: '"{{ SELF.application_port }}"' - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - 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 }}' - redis.server~redis.server#cache.image::ansible@kubernetes.cluster: - derived_from: redis.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: [] - delete: - implementation: - primary: Ansible - operation_host: ORCHESTRATOR - inputs: - playbook: - q: [] - redis.server~software.application#apt.package::ansible@*->remote.machine: - derived_from: redis.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: run setup script - ansible.builtin.shell: curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - args: - executable: /bin/bash - when: '".artifacts::apt_package::script" | eval != ""' - - name: add apt key - ansible.builtin.apt_key: - url: '{{ ".artifacts::apt_package::key" | eval }}' - keyring: /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - state: present - when: '".artifacts::apt_package::key" | eval != ""' - - name: add apt repository - ansible.builtin.apt_repository: - repo: deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }} - filename: '{{ ".artifacts::apt_package::repository" | eval }}' - state: present - when: '".artifacts::apt_package::source" | eval != ""' - - name: update apt cache - ansible.builtin.apt: - update_cache: 'yes' - - name: install dependencies - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }}' - state: present - when: '".artifacts::apt_package::dependencies" | eval != ""' - - name: install package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: present - environment: '{{ ".artifacts::apt_package::env" | eval | split | map("split", "=") | community.general.dict }}' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - - name: uninstall package - ansible.builtin.apt: - name: '{{ ".artifacts::apt_package::file" | eval }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - redis.server~software.application#tar.archive::ansible@*->remote.machine: - derived_from: redis.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::tar_archive::file" | eval).startswith("http") - - name: extract deployment artifact from URL in application directory - ansible.builtin.unarchive: - src: '{{ ".artifacts::tar_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - remote_src: 'yes' - extra_opts: '{{ ".artifacts::tar_archive::extra_opts" | eval | map_value }}' - when: (".artifacts::tar_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: |- - CACHE_NAME="{{ SELF.cache_name }}" - CACHE_PORT="{{ SELF.cache_port }}" - APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" - APPLICATION_NAME="{{ SELF.application_name }}" - APPLICATION_PORT="{{ SELF.application_port }}" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - redis.server~software.application#zip.archive::ansible@*->remote.machine: - derived_from: redis.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - create: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: install operational dependencies - ansible.builtin.apt: - name: unzip - update_cache: 'yes' - - name: create application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: directory - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: extract deployment artifact in application directory - ansible.builtin.unarchive: - src: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - dest: '{{ SELF.application_directory }}' - extra_opts: '{{ ".artifacts::zip_archive::extra_opts" | eval | map_value }}' - when: not (".artifacts::zip_archive::file" | eval).startswith("http") - - name: create vintner directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}/.vintner' - state: directory - - name: create .env file - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.env' - content: |- - CACHE_NAME="{{ SELF.cache_name }}" - CACHE_PORT="{{ SELF.cache_port }}" - APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" - APPLICATION_NAME="{{ SELF.application_name }}" - APPLICATION_PORT="{{ SELF.application_port }}" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/create.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - mode: '0755' - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/create.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_create != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - configure: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/configure.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - mode: '0755' - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/configure.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_configure != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - start: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "start" missing - when: SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/start.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - mode: '0755' - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/start.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_start != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - stop: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: assert management operation - ansible.builtin.fail: - dest: Management operation "stop" missing - when: SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/stop.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - mode: '0755' - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/stop.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_stop != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - delete: - implementation: - primary: Ansible - operation_host: HOST - environment: - ANSIBLE_HOST_KEY_CHECKING: 'False' - inputs: - playbook: - q: - - name: wait for ssh - wait_for_connection: - - name: copy management operation - ansible.builtin.copy: - dest: '{{ SELF.application_directory }}/.vintner/delete.sh' - content: |- - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - mode: '0755' - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: call management operation - ansible.builtin.shell: . .env && . .vintner/delete.sh - args: - chdir: '{{ SELF.application_directory }}' - executable: /bin/bash - when: SELF._management_delete != "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" - - name: delete application directory - ansible.builtin.file: - path: '{{ SELF.application_directory }}' - state: absent - playbookArgs: - - '--become' - - '--key-file={{ SELF.os_ssh_key_file }}' - - '--user={{ SELF.os_ssh_user }}' - redis.server~redis.server#cache.image::terraform@gcp.memorystore: - derived_from: redis.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - environment: - GOOGLE_APPLICATION_CREDENTIALS: - eval: .::gcp_service_account_file - delete: - implementation: - primary: Terraform - environment: - GOOGLE_APPLICATION_CREDENTIALS: - eval: .::gcp_service_account_file - defaults: - inputs: - main: - terraform: - - required_providers: - - google: - source: hashicorp/google - version: 5.39.1 - mysql: - source: petoju/mysql - version: 3.0.48 - provider: - google: - - credentials: '{{ SELF.gcp_service_account_file }}' - project: '{{ SELF.gcp_project }}' - region: '{{ SELF.gcp_region }}' - resource: {} - redis.server~redis.server#cache.image::terraform@docker.engine->local.machine: - derived_from: redis.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: unix:///var/run/docker.sock - resource: - docker_container: - application: - - env: - - CACHE_NAME={{ SELF.cache_name }} - - CACHE_PORT={{ SELF.cache_port }} - - APPLICATION_PROTOCOL={{ SELF.application_protocol }} - - APPLICATION_NAME={{ SELF.application_name }} - - APPLICATION_PORT={{ SELF.application_port }} - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - redis.server~redis.server#cache.image::terraform@docker.engine->remote.machine: - derived_from: redis.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - terraform: - - required_providers: - - docker: - source: kreuzwerker/docker - version: 3.0.2 - provider: - docker: - - host: ssh://{{ SELF.os_ssh_user }}@{{ SELF.os_ssh_host }}:22 - ssh_opts: - - '-i' - - '{{ SELF.os_ssh_key_file }}' - - '-o' - - IdentitiesOnly=yes - - '-o' - - BatchMode=yes - - '-o' - - UserKnownHostsFile=/dev/null - - '-o' - - StrictHostKeyChecking=no - resource: - docker_container: - application: - - env: - - CACHE_NAME={{ SELF.cache_name }} - - CACHE_PORT={{ SELF.cache_port }} - - APPLICATION_PROTOCOL={{ SELF.application_protocol }} - - APPLICATION_NAME={{ SELF.application_name }} - - APPLICATION_PORT={{ SELF.application_port }} - image: ${docker_image.image.image_id} - name: '{{ SELF.application_name }}' - network_mode: host - docker_image: - image: - - name: '{{ ".artifacts::docker_image::file" | eval }}' - redis.server~redis.server#cache.image::terraform@kubernetes.cluster: - derived_from: redis.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - gcp_service_account_file: - type: string - default: - get_input: gcp_service_account_file - gcp_region: - type: string - default: - get_input: gcp_region - gcp_project: - type: string - default: - get_input: gcp_project - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - environment: - GOOGLE_APPLICATION_CREDENTIALS: - eval: .::gcp_service_account_file - delete: - implementation: - primary: Terraform - environment: - GOOGLE_APPLICATION_CREDENTIALS: - eval: .::gcp_service_account_file - defaults: - inputs: - main: - terraform: [] - provider: {} - resource: {} - redis.server~software.application#apt.archive::terraform@*->remote.machine: - derived_from: redis.server - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - content: | - #!/usr/bin/bash - set -e - - # Run setup script - if [[ "{{ ".artifacts::apt_package::script" | eval }}" != "" ]]; then - curl -fsSL {{ ".artifacts::apt_package::script" | eval }} | sudo -E bash - - fi - - # Add apt key - if [[ "{{ ".artifacts::apt_package::key" | eval }}" != "" ]]; then - curl -1sLf {{ ".artifacts::apt_package::key" | eval }} | gpg --dearmor --yes -o /usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg - fi - - # Add apt repository - if [[ "{{ ".artifacts::apt_package::source" | eval }}" != "" ]]; then - echo "deb [signed-by=/usr/share/keyrings/{{ ".artifacts::apt_package::repository" | eval }}.gpg] {{ ".artifacts::apt_package::source" | eval }}" | tee {{ ".artifacts::apt_package::repository" | eval }} - fi - - # Update apt cache - apt-get update -y - - # Install dependencies - if [[ "{{ ".artifacts::apt_package::dependencies" | eval }}" != "" ]]; then - apt-get install {{ ".artifacts::apt_package::dependencies" | eval | split(",") | map("trim") }} -y - fi - - # Install package - {{ ".artifacts::apt_package::env" | eval }} apt-get install {{ ".artifacts::apt_package::file" | eval }} -y - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - CACHE_NAME="{{ SELF.cache_name }}" - CACHE_PORT="{{ SELF.cache_port }}" - APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" - APPLICATION_NAME="{{ SELF.application_name }}" - APPLICATION_PORT="{{ SELF.application_port }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::apt_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-redis.server {{ ".artifacts::apt_archive::file" | eval }} - fi - - # Extract deployment artifact - undefined - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-redis.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-redis.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-redis.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-redis.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - - # Uninstall package - apt-get uninstall {{ ".artifacts::apt_package::file" | eval }} -y - destination: /tmp/delete-redis.server.sh - remote-exec: - - inline: - - sudo bash /tmp/create-redis.server.sh - - sudo bash /tmp/configure-redis.server.sh - - sudo bash /tmp/start-redis.server.sh - - inline: - - sudo bash /tmp/stop-redis.server.sh - - sudo bash /tmp/delete-redis.server.sh - when: destroy - redis.server~software.application#tar.archive::terraform@*->remote.machine: - derived_from: redis.server - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::tar_archive::file" | eval }}' - destination: /tmp/artifact-redis.server - count: '{{ (not (".artifacts::tar_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - CACHE_NAME="{{ SELF.cache_name }}" - CACHE_PORT="{{ SELF.cache_port }}" - APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" - APPLICATION_NAME="{{ SELF.application_name }}" - APPLICATION_PORT="{{ SELF.application_port }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::tar_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-redis.server {{ ".artifacts::tar_archive::file" | eval }} - fi - - # Extract deployment artifact - tar -xzf /tmp/artifact-redis.server -C {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-redis.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-redis.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-redis.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-redis.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-redis.server.sh - remote-exec: - - inline: - - sudo bash /tmp/create-redis.server.sh - - sudo bash /tmp/configure-redis.server.sh - - sudo bash /tmp/start-redis.server.sh - - inline: - - sudo bash /tmp/stop-redis.server.sh - - sudo bash /tmp/delete-redis.server.sh - when: destroy - redis.server~software.application#zip.archive::terraform@*->remote.machine: - derived_from: redis.server - metadata: - vintner_generated: 'true' - properties: - os_ssh_user: - type: string - default: - get_input: os_ssh_user - os_ssh_key_file: - type: string - default: - get_input: os_ssh_key_file - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - application_directory: - type: string - default: - concat: - - /var/lib/ - - get_property: - - SELF - - application_name - interfaces: - Standard: - operations: - configure: - implementation: - primary: Terraform - delete: - implementation: - primary: Terraform - defaults: - inputs: - main: - resource: - terraform_data: - vm: - - connection: - - host: '{{ SELF.os_ssh_host }}' - private_key: ${file("{{ SELF.os_ssh_key_file }}")} - type: ssh - user: '{{ SELF.os_ssh_user }}' - provisioner: - file: - - source: '{{ "project" | get_dir }}/ensemble/{{ ".artifacts::zip_archive::file" | eval }}' - destination: /tmp/artifact-redis.server - count: '{{ (not (".artifacts::zip_archive::file" | eval).startswith("http")) | ternary(1, 0) }}' - - content: | - #!/usr/bin/bash - set -e - - # Create application directory - mkdir -p {{ SELF.application_directory }} - - # Create application environment - cat < {{ SELF.application_directory }}/.env - CACHE_NAME="{{ SELF.cache_name }}" - CACHE_PORT="{{ SELF.cache_port }}" - APPLICATION_PROTOCOL="{{ SELF.application_protocol }}" - APPLICATION_NAME="{{ SELF.application_name }}" - APPLICATION_PORT="{{ SELF.application_port }}" - EOF>> - - # Download deployment artifact if required - if [[ "{{ ".artifacts::zip_archive::file" | eval }}" == http* ]]; then - wget -O /tmp/artifact-redis.server {{ ".artifacts::zip_archive::file" | eval }} - fi - - # Extract deployment artifact - unzip /tmp/artifact-redis.server -d {{ SELF.application_directory }} {{ ".artifacts::tar_archive::extra_opts" | eval | map_value }} - - # Create vintner directory - mkdir -p {{ SELF.application_directory }}/.vintner - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/create.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_create == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_create) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/create.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/create.sh - destination: /tmp/create-redis.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/configure.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_configure == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_configure) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/configure.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/configure.sh - destination: /tmp/configure-redis.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_start | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "start" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/start.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_start == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_start) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/start.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/start.sh - destination: /tmp/start-redis.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Assert operation - if [[ "{{ SELF._management_stop | split('\n') | first }}" == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ]]; then - echo 'Management operation "stop" missing' - exit 1 - fi - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/stop.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_stop == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_stop) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/stop.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/stop.sh - destination: /tmp/stop-redis.server.sh - - content: | - #!/usr/bin/bash - set -e - - # Copy operation - cat < {{ SELF.application_directory }}/.vintner/delete.sh - #!/usr/bin/bash - set -e - - {{ (SELF._management_delete == "VINTNER_MANAGEMENT_OPERATION_UNDEFINED" ) | ternary("echo 0", SELF._management_delete) }} - EOF>> - chmod +x {{ SELF.application_directory }}/.vintner/delete.sh - - # Execute operation - cd {{ SELF.application_directory }} - . .env - . .vintner/delete.sh - - # Delete application directory - rm -rf "{{ SELF.application_directory }}" - destination: /tmp/delete-redis.server.sh - remote-exec: - - inline: - - sudo bash /tmp/create-redis.server.sh - - sudo bash /tmp/configure-redis.server.sh - - sudo bash /tmp/start-redis.server.sh - - inline: - - sudo bash /tmp/stop-redis.server.sh - - sudo bash /tmp/delete-redis.server.sh - when: destroy - redis.server~redis.server#cache.image::compose@docker.engine->local.machine: - derived_from: redis.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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: - CACHE_NAME: '"{{ SELF.cache_name }}"' - CACHE_PORT: '"{{ SELF.cache_port }}"' - APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' - APPLICATION_NAME: '"{{ SELF.application_name }}"' - APPLICATION_PORT: '"{{ SELF.application_port }}"' - - name: apply compose - ansible.builtin.shell: docker compose -f {{ compose.path }} up -d - args: - executable: /usr/bin/bash - 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: - CACHE_NAME: '"{{ SELF.cache_name }}"' - CACHE_PORT: '"{{ SELF.cache_port }}"' - APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' - APPLICATION_NAME: '"{{ SELF.application_name }}"' - APPLICATION_PORT: '"{{ SELF.application_port }}"' - - name: apply compose - ansible.builtin.shell: docker compose -f {{ compose.path }} down - args: - executable: /usr/bin/bash - redis.server~redis.server#cache.image::compose@docker.engine->remote.machine: - derived_from: redis.server - metadata: - vintner_generated: 'true' - vintner_orchestrator: unfurl - properties: - os_ssh_host: - type: string - default: - eval: .::.requirements::[.name=host]::.target::management_address - attributes: - application_address: - type: string - default: 127.0.0.1 - interfaces: - Standard: - operations: - create: - 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: - CACHE_NAME: '"{{ SELF.cache_name }}"' - CACHE_PORT: '"{{ SELF.cache_port }}"' - APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' - APPLICATION_NAME: '"{{ SELF.application_name }}"' - APPLICATION_PORT: '"{{ SELF.application_port }}"' - - 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 }}' - 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: - CACHE_NAME: '"{{ SELF.cache_name }}"' - CACHE_PORT: '"{{ SELF.cache_port }}"' - APPLICATION_PROTOCOL: '"{{ SELF.application_protocol }}"' - APPLICATION_NAME: '"{{ SELF.application_name }}"' - APPLICATION_PORT: '"{{ SELF.application_port }}"' - - 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---industry---plus-maintenance-automated/lib/tosca-vintner-profile.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile.yaml deleted file mode 100644 index 8c2c83560a..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/tosca-vintner-profile.yaml +++ /dev/null @@ -1,21 +0,0 @@ -################################################### -# -# WARNING: Do not edit! This file is autogenerated! -# -################################################### - -tosca_definitions_version: tosca_simple_yaml_1_3 -description: TOSCA Profile for OpenTOSCA Vintner -metadata: - vintner_normative: 'true' - template_name: TOSCA Vintner Profile - template_author: Miles Stötzner - template_contact: miles.stoetzner@iste.uni-stuttgart.de - template_link: https://vintner.opentosca.org - template_version: 1.0.0-draft - template_id: tosca-vintner-profile - template_license: https://www.apache.org/licenses/LICENSE-2.0 - acknowledgments: Partially funded by the [German Federal Ministry for Economic Affairs and Climate Action (BMWK)](https://www.bmwk.de) as part of the research project [SofDCar (19S21002)](https://sofdcar.de). -imports: - - ./tosca-vintner-profile-core.yaml - - ./tosca-vintner-profile-extended.yaml diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/types.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/lib/types.yaml deleted file mode 100644 index ee9b69ba7c..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/lib/types.yaml +++ /dev/null @@ -1,4 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_3 -imports: - - tosca-vintner-profile.yaml - - retailer.yaml diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/clean.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/clean.sh deleted file mode 100755 index dc174b7f71..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/clean.sh +++ /dev/null @@ -1,11 +0,0 @@ -#! /usr/bin/bash -set -e - -# Set working directory -cd "$(dirname "$0")" - -# Load configuration -source configuration.sh - -# Clean -$VINTNER setup clean --force diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/code.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/code.sh deleted file mode 100755 index dbe3358fb5..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/code.sh +++ /dev/null @@ -1,11 +0,0 @@ -#! /usr/bin/bash -set -e - -# Set working directory -cd "$(dirname "$0")" - -# Load configuration -source configuration.sh - -# Open VS Code -$VINTNER instances code --instance ${TEMPLATE_NAME} \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.env b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.env deleted file mode 100644 index 047812aaf3..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.env +++ /dev/null @@ -1,5 +0,0 @@ -TEMPLATE_NAME="technology-gcp" -#VINTNER="node ../../../build/cli/index.js" -VINTNER="../../../task vintner" -ORCHESTRATOR="unfurl" -VARIANT="local" diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.sh deleted file mode 100755 index 9c517b8682..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/configuration.sh +++ /dev/null @@ -1,36 +0,0 @@ -#! /usr/bin/bash -set -e - -# Set working directory -cd "$(dirname "$0")" - -# Load configuration -source configuration.env - -# Check that TEMPLATE_NAME is defined -if [[ -z ${TEMPLATE_NAME} ]]; then - echo "TEMPLATE_NAME is not defined" - exit 1 -fi - -# Check that VINTNER is defined -if [[ -z ${VINTNER} ]]; then - echo "VINTNER is not defined" - exit 1 -fi - - -# Check that VARIANT is defined -if [[ -z ${VARIANT} ]]; then - echo "VARIANT is not defined" - exit 1 -fi - -# Check that ORCHESTRATOR is defined -if [[ -z ${ORCHESTRATOR} ]]; then - echo "ORCHESTRATOR is not defined" - exit 1 -fi - -# Set template directory -TEMPLATE_DIR=$(readlink -f $(dirname $0)/../) diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/continue.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/continue.sh deleted file mode 100755 index 4784e34fb6..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/continue.sh +++ /dev/null @@ -1,11 +0,0 @@ -#! /usr/bin/bash -set -e - -# Set working directory -cd "$(dirname "$0")" - -# Load configuration -source configuration.sh - -# Continue deployment -$VINTNER instances continue --instance ${TEMPLATE_NAME} --force diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/deploy.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/deploy.sh deleted file mode 100755 index 00aaf273b2..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/deploy.sh +++ /dev/null @@ -1,16 +0,0 @@ -#! /usr/bin/bash -set -e - -# Set working directory -cd "$(dirname "$0")" - -# Load configuration -source configuration.sh - -$VINTNER template pull --dir ${TEMPLATE_DIR} -$VINTNER template implement --dir ${TEMPLATE_DIR} --experimental -$VINTNER templates import --template ${TEMPLATE_NAME} --path ${TEMPLATE_DIR} -$VINTNER instances init --instance ${TEMPLATE_NAME} --template ${TEMPLATE_NAME} -$VINTNER instances resolve --instance ${TEMPLATE_NAME} --inputs ${TEMPLATE_DIR}/tests/${VARIANT}/inputs.yaml -$VINTNER instances validate --instance ${TEMPLATE_NAME} --inputs ${TEMPLATE_DIR}/deployment-inputs.ignored.yaml -$VINTNER instances deploy --instance ${TEMPLATE_NAME} --inputs ${TEMPLATE_DIR}/deployment-inputs.ignored.yaml diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/enrich.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/enrich.sh deleted file mode 100755 index 8e2ca88227..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/enrich.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -set -e - -# Load configuration -source configuration.sh - -# Enrich -$VINTNER template enrich --template ${TEMPLATE_DIR}/variable-service-template.yaml --output ${TEMPLATE_DIR}/enriched.yaml diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/implement.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/implement.sh deleted file mode 100755 index 0ac779ce2c..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/implement.sh +++ /dev/null @@ -1,8 +0,0 @@ -#! /usr/bin/bash -set -e - -# Load configuration -source configuration.sh - -# Implement types -$VINTNER template implement --dir ${TEMPLATE_DIR} --experimental diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/pull.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/pull.sh deleted file mode 100755 index 90f0358264..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/pull.sh +++ /dev/null @@ -1,9 +0,0 @@ -#! /usr/bin/bash -set -e - -# Load configuration -source configuration.sh - -# Pull dependencies -$VINTNER template pull --dir ${TEMPLATE_DIR} - diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh deleted file mode 100755 index 60f7018a34..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/quality.sh +++ /dev/null @@ -1,13 +0,0 @@ -#! /usr/bin/bash -set -e - -# Load configuration -source configuration.sh - -# Quality -for dir in ../tests/*/; -#for dir in "../tests/gcp"; -do - dir=$(basename $dir) - echo "${dir}: $($VINTNER template quality --template ${TEMPLATE_DIR}/variable-service-template.yaml --experimental --inputs ${TEMPLATE_DIR}/tests/${dir}/inputs.yaml)" -done diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/reimport.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/reimport.sh deleted file mode 100755 index 5a7316f121..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/reimport.sh +++ /dev/null @@ -1,20 +0,0 @@ -#! /usr/bin/bash -set -e - -# Set working directory -cd "$(dirname "$0")" - -# Load configuration -source configuration.sh - -$VINTNER instances undeploy --instance ${TEMPLATE_NAME} || true - -$VINTNER instances delete --instance ${TEMPLATE_NAME} --force || true -$VINTNER templates delete --template ${TEMPLATE_NAME} || true - -$VINTNER template pull --dir ${TEMPLATE_DIR} -$VINTNER templates import --template ${TEMPLATE_NAME} --path ${TEMPLATE_DIR} -$VINTNER instances init --instance ${TEMPLATE_NAME} --template ${TEMPLATE_NAME} -$VINTNER instances resolve --instance ${TEMPLATE_NAME} --inputs ${TEMPLATE_DIR}/tests/${VARIANT}/inputs.yaml -$VINTNER instances validate --instance ${TEMPLATE_NAME} --inputs ${TEMPLATE_DIR}/deployment-inputs.ignored.yaml -$VINTNER instances deploy --instance ${TEMPLATE_NAME} --inputs ${TEMPLATE_DIR}/deployment-inputs.ignored.yaml diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/setup.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/setup.sh deleted file mode 100755 index 519cac182c..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/setup.sh +++ /dev/null @@ -1,14 +0,0 @@ -#! /usr/bin/bash -set -e - -# Set working directory -cd "$(dirname "$0")" - -# Load configuration -source configuration.sh - -# Setup -$VINTNER setup init -$VINTNER orchestrators init ${ORCHESTRATOR} -$VINTNER orchestrators enable --orchestrator ${ORCHESTRATOR} -$VINTNER orchestrators attest --orchestrator ${ORCHESTRATOR} \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-001.txt b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-001.txt deleted file mode 100644 index 8fdd476737..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-001.txt +++ /dev/null @@ -1,107 +0,0 @@ - -The technology rules of our case study. Qualities range from bad (0) to good (1). -┌─────────┬──────────────┬────────────────────────┬─────────────────────────────────────────────┬─────────┐ -│ (index) │ Technology │ Component │ Hosting │ Quality │ -├─────────┼──────────────┼────────────────────────┼─────────────────────────────────────────────┼─────────┤ -│ 0 │ 'ansible' │ 'software.application' │ [ 'software.runtime', 'openstack.machine' ] │ 1 │ -│ 1 │ 'ansible' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ -│ 2 │ 'ansible' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ -│ 3 │ 'ansible' │ 'software.application' │ [ 'gcp.appengine' ] │ 0 │ -│ 4 │ 'ansible' │ 'software.runtime' │ [ 'openstack.machine' ] │ 1 │ -│ 5 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ -│ 6 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ -│ 7 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ -│ 8 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ -│ 9 │ 'ansible' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 1 │ -│ 10 │ 'ansible' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ -│ 11 │ 'ansible' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ -│ 12 │ 'ansible' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ -│ 13 │ 'ansible' │ 'ingress' │ [ 'openstack.machine' ] │ 1 │ -│ 14 │ 'ansible' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ -│ 15 │ 'ansible' │ 'openstack.machine' │ undefined │ 0.5 │ -│ 16 │ 'ansible' │ 'gcp.service' │ undefined │ 1 │ -│ 17 │ 'terraform' │ 'software.application' │ [ 'software.runtime', 'openstack.machine' ] │ 0 │ -│ 18 │ 'terraform' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ -│ 19 │ 'terraform' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ -│ 20 │ 'terraform' │ 'software.application' │ [ 'gcp.appengine' ] │ 1 │ -│ 21 │ 'terraform' │ 'software.runtime' │ [ 'openstack.machine' ] │ 0 │ -│ 22 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ -│ 23 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ -│ 24 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ -│ 25 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ -│ 26 │ 'terraform' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 0 │ -│ 27 │ 'terraform' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ -│ 28 │ 'terraform' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ -│ 29 │ 'terraform' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ -│ 30 │ 'terraform' │ 'ingress' │ [ 'openstack.machine' ] │ 0 │ -│ 31 │ 'terraform' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ -│ 32 │ 'terraform' │ 'openstack.machine' │ undefined │ 1 │ -│ 33 │ 'terraform' │ 'gcp.service' │ undefined │ 1 │ -│ 34 │ 'kubernetes' │ 'software.application' │ [ 'kubernetes' ] │ 1 │ -│ 35 │ 'kubernetes' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 0 │ -│ 36 │ 'kubernetes' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 1 │ -│ 37 │ 'kubernetes' │ 'ingress' │ [ 'kubernetes' ] │ 1 │ -│ 38 │ 'docker' │ 'software.application' │ [ 'docker.engine' ] │ 1 │ -│ 39 │ 'docker' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 0 │ -│ 40 │ 'docker' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 1 │ -└─────────┴──────────────┴────────────────────────┴─────────────────────────────────────────────┴─────────┘ - -Metrics relevant when modeling the different scenarios -┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────┐ -│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ -├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────┤ -│ 0 │ 'EDMM Docker Variant' │ 1 │ 49 │ 0 │ 12 │ 187 │ │ -│ 1 │ 'EDMM GCP Variant' │ 1 │ 57 │ 0 │ 12 │ 204 │ │ -│ 2 │ 'EDMM OS Large Variant' │ 1 │ 93 │ 0 │ 18 │ 284 │ │ -│ 3 │ 'EDMM OS Medium Variant' │ 1 │ 93 │ 0 │ 18 │ 284 │ │ -│ 4 │ 'EDMM Total (EDMM Docker Variant, EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant)' │ 4 │ 292 │ 0 │ 60 │ 959 │ 'EDMM Total' │ -│ 5 │ 'VDMM Baseline Default' │ 1 │ 192 │ 10 │ 44 │ 557 │ │ -│ 6 │ 'VDMM+ Default Manual' │ 1 │ 130 │ 42 │ 45 │ 461 │ │ -│ 7 │ 'VDMM+ Default Automated Random' │ 1 │ 130 │ 5 │ 0 │ 371 │ │ -│ 8 │ 'VDMM+ Default Automated Counting' │ 1 │ 130 │ 5 │ 0 │ 372 │ │ -│ 9 │ 'VDMM+ Default Automated Quality' │ 1 │ 130 │ 5 │ 0 │ 368 │ │ -└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────┘ - -Qualities of the derived deployment models, i.e., the deployment variants, of the different scenarios ranging from bad (0) to good (1). -┌─────────┬──────────────┬────────┬─────────────┬─────────────┬────────────────┬─────────┐ -│ (index) │ scenario │ expert │ non_expert │ random │ counting │ quality │ -├─────────┼──────────────┼────────┼─────────────┼─────────────┼────────────────┼─────────┤ -│ 0 │ 'docker' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.92 ] │ 1 │ -│ 1 │ 'gcp' │ 1 │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ 1 │ -│ 2 │ 'kubernetes' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.92 ] │ 1 │ -│ 3 │ 'os-large' │ 1 │ [ 0.08, 1 ] │ [ 0.08, 1 ] │ [ 0.11, 0.97 ] │ 1 │ -│ 4 │ 'os-medium' │ 1 │ [ 0.08, 1 ] │ [ 0.08, 1 ] │ [ 0.11, 0.97 ] │ 1 │ -└─────────┴──────────────┴────────┴─────────────┴─────────────┴────────────────┴─────────┘ - -Metrics relevant when modeling the maintenance scenario of our case study -┌─────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────────────────┐ -│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ -├─────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────────────────┤ -│ 0 │ 'EDMM Kubernetes' │ 1 │ 60 │ 0 │ 12 │ 209 │ │ -│ 1 │ 'EDMM Total Maintenance (EDMM Docker Variant, EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant, EDMM Kubernetes)' │ 5 │ 352 │ 0 │ 72 │ 1168 │ 'EDMM Total Maintenance' │ -│ 2 │ 'VDMM Baseline Maintenance' │ 1 │ 262 │ 29 │ 56 │ 752 │ │ -│ 3 │ 'VDMM+ Maintenance Manual' │ 1 │ 157 │ 60 │ 58 │ 554 │ │ -│ 4 │ 'VDMM+ Maintenance Automated Random' │ 1 │ 157 │ 10 │ 0 │ 437 │ │ -│ 5 │ 'VDMM+ Maintenance Automated Counting' │ 1 │ 157 │ 10 │ 0 │ 438 │ │ -│ 6 │ 'VDMM+ Maintenance Automated Quality' │ 1 │ 157 │ 10 │ 0 │ 434 │ │ -└─────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────────────────┘ - -From Default to Maintained (Absolut to previous) -┌─────────┬─────────────────────────────────────────────────────────────────────────┬──────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ -│ (index) │ scenario │ models_absolute_diff │ elements_absolute_diff │ conditions_absolute_diff │ technology_assignments_absolute_diff │ lines_of_code_absolute_diff │ -├─────────┼─────────────────────────────────────────────────────────────────────────┼──────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ -│ 0 │ 'EDMM Total Maintenance - EDMM Total' │ 1 │ 60 │ 0 │ 12 │ 209 │ -│ 1 │ 'VDMM Baseline Maintenance - VDMM Baseline Default' │ 0 │ 70 │ 19 │ 12 │ 195 │ -│ 2 │ 'VDMM+ Maintenance Manual - VDMM+ Default Manual' │ 0 │ 27 │ 18 │ 13 │ 93 │ -│ 3 │ 'VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality' │ 0 │ 27 │ 5 │ 0 │ 66 │ -└─────────┴─────────────────────────────────────────────────────────────────────────┴──────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ - -From Default to Maintained (Relative to change to baseline) -┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ -│ (index) │ scenario │ elements_relative_diff │ conditions_relative_diff │ technology_assignments_relative_diff │ lines_of_code_relative_diff │ -├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ -│ 0 │ '(VDMM+ Maintenance Manual - VDMM+ Default Manual) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.39 │ 0.95 │ 1.08 │ 0.48 │ -│ 1 │ '(VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.39 │ 0.26 │ 0 │ 0.34 │ -└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ - -> Original \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-002.txt b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-002.txt deleted file mode 100644 index 70464a2d8a..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-002.txt +++ /dev/null @@ -1,106 +0,0 @@ - -The technology rules of our case study. Qualities range from bad (0) to good (1). -┌─────────┬──────────────┬────────────────────────┬─────────────────────────────────────────────┬─────────┐ -│ (index) │ Technology │ Component │ Hosting │ Quality │ -├─────────┼──────────────┼────────────────────────┼─────────────────────────────────────────────┼─────────┤ -│ 0 │ 'ansible' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ -│ 1 │ 'ansible' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ -│ 2 │ 'ansible' │ 'software.application' │ [ 'gcp.appengine' ] │ 0 │ -│ 3 │ 'ansible' │ 'software.application' │ [ 'openstack.machine' ] │ 1 │ -│ 4 │ 'ansible' │ 'docker.engine' │ [ 'openstack.machine' ] │ 1 │ -│ 5 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ -│ 6 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ -│ 7 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ -│ 8 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ -│ 9 │ 'ansible' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 1 │ -│ 10 │ 'ansible' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ -│ 11 │ 'ansible' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ -│ 12 │ 'ansible' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ -│ 13 │ 'ansible' │ 'ingress' │ [ 'openstack.machine' ] │ 1 │ -│ 14 │ 'ansible' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ -│ 15 │ 'ansible' │ 'openstack.machine' │ undefined │ 0.5 │ -│ 16 │ 'ansible' │ 'gcp.service' │ undefined │ 1 │ -│ 17 │ 'terraform' │ 'software.application' │ [ 'software.runtime', 'openstack.machine' ] │ 0 │ -│ 18 │ 'terraform' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ -│ 19 │ 'terraform' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ -│ 20 │ 'terraform' │ 'software.application' │ [ 'gcp.appengine' ] │ 1 │ -│ 21 │ 'terraform' │ 'software.application' │ [ 'openstack.machine' ] │ 0 │ -│ 22 │ 'terraform' │ 'docker.engine' │ [ 'openstack.machine' ] │ 0 │ -│ 23 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ -│ 24 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ -│ 25 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ -│ 26 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ -│ 27 │ 'terraform' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 0 │ -│ 28 │ 'terraform' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ -│ 29 │ 'terraform' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ -│ 30 │ 'terraform' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ -│ 31 │ 'terraform' │ 'ingress' │ [ 'openstack.machine' ] │ 0 │ -│ 32 │ 'terraform' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ -│ 33 │ 'terraform' │ 'openstack.machine' │ undefined │ 1 │ -│ 34 │ 'terraform' │ 'gcp.service' │ undefined │ 1 │ -│ 35 │ 'kubernetes' │ 'software.application' │ [ 'kubernetes' ] │ 1 │ -│ 36 │ 'kubernetes' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 0 │ -│ 37 │ 'kubernetes' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 1 │ -│ 38 │ 'kubernetes' │ 'ingress' │ [ 'kubernetes' ] │ 1 │ -│ 39 │ 'docker' │ 'software.application' │ [ 'docker.engine' ] │ 1 │ -│ 40 │ 'docker' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 0 │ -│ 41 │ 'docker' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 1 │ -└─────────┴──────────────┴────────────────────────┴─────────────────────────────────────────────┴─────────┘ - -Metrics relevant when modeling the different scenarios -┌─────────┬────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────┐ -│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ -├─────────┼────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────┤ -│ 0 │ 'EDMM GCP Variant' │ 1 │ 57 │ 0 │ 14 │ 206 │ │ -│ 1 │ 'EDMM OS Large Variant' │ 1 │ 86 │ 0 │ 18 │ 269 │ │ -│ 2 │ 'EDMM OS Medium Variant' │ 1 │ 86 │ 0 │ 18 │ 269 │ │ -│ 3 │ 'EDMM Total (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant)' │ 3 │ 229 │ 0 │ 50 │ 744 │ 'EDMM Total' │ -│ 4 │ 'VDMM Baseline Default' │ 1 │ 138 │ 8 │ 31 │ 424 │ │ -│ 5 │ 'VDMM+ Default Manual' │ 1 │ 109 │ 27 │ 31 │ 389 │ │ -│ 6 │ 'VDMM+ Default Automated Random' │ 1 │ 109 │ 4 │ 0 │ 326 │ │ -│ 7 │ 'VDMM+ Default Automated Counting' │ 1 │ 109 │ 4 │ 0 │ 327 │ │ -│ 8 │ 'VDMM+ Default Automated Quality' │ 1 │ 109 │ 4 │ 0 │ 323 │ │ -└─────────┴────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────┘ - -Qualities of the derived deployment models, i.e., the deployment variants, of the different scenarios ranging from bad (0) to good (1). -┌─────────┬──────────────┬────────┬─────────────┬─────────────┬────────────────┬─────────┐ -│ (index) │ scenario │ expert │ non_expert │ random │ counting │ quality │ -├─────────┼──────────────┼────────┼─────────────┼─────────────┼────────────────┼─────────┤ -│ 0 │ 'gcp' │ 1 │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ 1 │ -│ 1 │ 'kubernetes' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.92 ] │ 1 │ -│ 2 │ 'os-large' │ 1 │ [ 0.33, 1 ] │ [ 0.33, 1 ] │ [ 0.42, 0.67 ] │ 1 │ -│ 3 │ 'os-medium' │ 1 │ [ 0.33, 1 ] │ [ 0.33, 1 ] │ [ 0.42, 0.67 ] │ 1 │ -└─────────┴──────────────┴────────┴─────────────┴─────────────┴────────────────┴─────────┘ - -Metrics relevant when modeling the maintenance scenario of our case study -┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────────────────┐ -│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ -├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────────────────┤ -│ 0 │ 'EDMM Kubernetes' │ 1 │ 60 │ 0 │ 13 │ 210 │ │ -│ 1 │ 'EDMM Total Maintenance (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant, EDMM Kubernetes)' │ 4 │ 289 │ 0 │ 63 │ 954 │ 'EDMM Total Maintenance' │ -│ 2 │ 'VDMM Baseline Maintenance' │ 1 │ 204 │ 23 │ 43 │ 606 │ │ -│ 3 │ 'VDMM+ Maintenance Manual' │ 1 │ 136 │ 44 │ 43 │ 479 │ │ -│ 4 │ 'VDMM+ Maintenance Automated Random' │ 1 │ 136 │ 9 │ 0 │ 394 │ │ -│ 5 │ 'VDMM+ Maintenance Automated Counting' │ 1 │ 136 │ 9 │ 0 │ 395 │ │ -│ 6 │ 'VDMM+ Maintenance Automated Quality' │ 1 │ 136 │ 9 │ 0 │ 391 │ │ -└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────────────────┘ - -From Default to Maintained (Absolut to previous) -┌─────────┬─────────────────────────────────────────────────────────────────────────┬──────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ -│ (index) │ scenario │ models_absolute_diff │ elements_absolute_diff │ conditions_absolute_diff │ technology_assignments_absolute_diff │ lines_of_code_absolute_diff │ -├─────────┼─────────────────────────────────────────────────────────────────────────┼──────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ -│ 0 │ 'EDMM Total Maintenance - EDMM Total' │ 1 │ 60 │ 0 │ 13 │ 210 │ -│ 1 │ 'VDMM Baseline Maintenance - VDMM Baseline Default' │ 0 │ 66 │ 15 │ 12 │ 182 │ -│ 2 │ 'VDMM+ Maintenance Manual - VDMM+ Default Manual' │ 0 │ 27 │ 17 │ 12 │ 90 │ -│ 3 │ 'VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality' │ 0 │ 27 │ 5 │ 0 │ 68 │ -└─────────┴─────────────────────────────────────────────────────────────────────────┴──────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ - -From Default to Maintained (Relative to change to baseline) -┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ -│ (index) │ scenario │ elements_relative_diff │ conditions_relative_diff │ technology_assignments_relative_diff │ lines_of_code_relative_diff │ -├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ -│ 0 │ '(VDMM+ Maintenance Manual - VDMM+ Default Manual) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.41 │ 1.13 │ 1 │ 0.49 │ -│ 1 │ '(VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.41 │ 0.33 │ 0 │ 0.37 │ -└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ - -> Diff: Docker on VM \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-003.txt b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-003.txt deleted file mode 100644 index 09a831f22a..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-003.txt +++ /dev/null @@ -1,106 +0,0 @@ - -The technology rules of our case study. Qualities range from bad (0) to good (1). -┌─────────┬──────────────┬────────────────────────┬─────────────────────────────────────────────┬─────────┐ -│ (index) │ Technology │ Component │ Hosting │ Quality │ -├─────────┼──────────────┼────────────────────────┼─────────────────────────────────────────────┼─────────┤ -│ 0 │ 'ansible' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ -│ 1 │ 'ansible' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ -│ 2 │ 'ansible' │ 'software.application' │ [ 'gcp.appengine' ] │ 0 │ -│ 3 │ 'ansible' │ 'software.application' │ [ 'openstack.machine' ] │ 1 │ -│ 4 │ 'ansible' │ 'docker.engine' │ [ 'openstack.machine' ] │ 1 │ -│ 5 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ -│ 6 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ -│ 7 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ -│ 8 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ -│ 9 │ 'ansible' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 1 │ -│ 10 │ 'ansible' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ -│ 11 │ 'ansible' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ -│ 12 │ 'ansible' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ -│ 13 │ 'ansible' │ 'ingress' │ [ 'openstack.machine' ] │ 1 │ -│ 14 │ 'ansible' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ -│ 15 │ 'ansible' │ 'openstack.machine' │ undefined │ 0.5 │ -│ 16 │ 'ansible' │ 'gcp.service' │ undefined │ 1 │ -│ 17 │ 'terraform' │ 'software.application' │ [ 'software.runtime', 'openstack.machine' ] │ 0 │ -│ 18 │ 'terraform' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ -│ 19 │ 'terraform' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ -│ 20 │ 'terraform' │ 'software.application' │ [ 'gcp.appengine' ] │ 1 │ -│ 21 │ 'terraform' │ 'software.application' │ [ 'openstack.machine' ] │ 0 │ -│ 22 │ 'terraform' │ 'docker.engine' │ [ 'openstack.machine' ] │ 0 │ -│ 23 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ -│ 24 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ -│ 25 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ -│ 26 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ -│ 27 │ 'terraform' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 0 │ -│ 28 │ 'terraform' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ -│ 29 │ 'terraform' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ -│ 30 │ 'terraform' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ -│ 31 │ 'terraform' │ 'ingress' │ [ 'openstack.machine' ] │ 0 │ -│ 32 │ 'terraform' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ -│ 33 │ 'terraform' │ 'openstack.machine' │ undefined │ 1 │ -│ 34 │ 'terraform' │ 'gcp.service' │ undefined │ 1 │ -│ 35 │ 'kubernetes' │ 'software.application' │ [ 'kubernetes' ] │ 1 │ -│ 36 │ 'kubernetes' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 0 │ -│ 37 │ 'kubernetes' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 1 │ -│ 38 │ 'kubernetes' │ 'ingress' │ [ 'kubernetes' ] │ 1 │ -│ 39 │ 'docker' │ 'software.application' │ [ 'docker.engine' ] │ 1 │ -│ 40 │ 'docker' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 0 │ -│ 41 │ 'docker' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 1 │ -└─────────┴──────────────┴────────────────────────┴─────────────────────────────────────────────┴─────────┘ - -Metrics relevant when modeling the different scenarios -┌─────────┬────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────┐ -│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ -├─────────┼────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────┤ -│ 0 │ 'EDMM GCP Variant' │ 1 │ 74 │ 0 │ 14 │ 227 │ │ -│ 1 │ 'EDMM OS Large Variant' │ 1 │ 104 │ 0 │ 18 │ 292 │ │ -│ 2 │ 'EDMM OS Medium Variant' │ 1 │ 104 │ 0 │ 18 │ 292 │ │ -│ 3 │ 'EDMM Total (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant)' │ 3 │ 282 │ 0 │ 50 │ 811 │ 'EDMM Total' │ -│ 4 │ 'VDMM Baseline Default' │ 1 │ 173 │ 8 │ 31 │ 468 │ │ -│ 5 │ 'VDMM+ Default Manual' │ 1 │ 127 │ 27 │ 31 │ 412 │ │ -│ 6 │ 'VDMM+ Default Automated Random' │ 1 │ 127 │ 4 │ 0 │ 350 │ │ -│ 7 │ 'VDMM+ Default Automated Counting' │ 1 │ 127 │ 4 │ 0 │ 351 │ │ -│ 8 │ 'VDMM+ Default Automated Quality' │ 1 │ 127 │ 4 │ 0 │ 347 │ │ -└─────────┴────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────┘ - -Qualities of the derived deployment models, i.e., the deployment variants, of the different scenarios ranging from bad (0) to good (1). -┌─────────┬──────────────┬────────┬─────────────┬─────────────┬────────────────┬─────────┬──────────────────┐ -│ (index) │ scenario │ expert │ non_expert │ random │ counting │ quality │ quality_counting │ -├─────────┼──────────────┼────────┼─────────────┼─────────────┼────────────────┼─────────┼──────────────────┤ -│ 0 │ 'gcp' │ 1 │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ 1 │ 1 │ -│ 1 │ 'kubernetes' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.92 ] │ 1 │ 1 │ -│ 2 │ 'os-large' │ 1 │ [ 0.33, 1 ] │ [ 0.33, 1 ] │ [ 0.42, 0.67 ] │ 1 │ 1 │ -│ 3 │ 'os-medium' │ 1 │ [ 0.33, 1 ] │ [ 0.33, 1 ] │ [ 0.42, 0.67 ] │ 1 │ 1 │ -└─────────┴──────────────┴────────┴─────────────┴─────────────┴────────────────┴─────────┴──────────────────┘ - -Metrics relevant when modeling the maintenance scenario of our case study -┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────────────────┐ -│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ -├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────────────────┤ -│ 0 │ 'EDMM Kubernetes' │ 1 │ 78 │ 0 │ 13 │ 233 │ │ -│ 1 │ 'EDMM Total Maintenance (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant, EDMM Kubernetes)' │ 4 │ 360 │ 0 │ 63 │ 1044 │ 'EDMM Total Maintenance' │ -│ 2 │ 'VDMM Baseline Maintenance' │ 1 │ 257 │ 23 │ 43 │ 673 │ │ -│ 3 │ 'VDMM+ Maintenance Manual' │ 1 │ 154 │ 44 │ 43 │ 502 │ │ -│ 4 │ 'VDMM+ Maintenance Automated Random' │ 1 │ 154 │ 9 │ 0 │ 418 │ │ -│ 5 │ 'VDMM+ Maintenance Automated Counting' │ 1 │ 154 │ 9 │ 0 │ 419 │ │ -│ 6 │ 'VDMM+ Maintenance Automated Quality' │ 1 │ 154 │ 9 │ 0 │ 415 │ │ -└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────────────────┘ - -From Default to Maintained (Absolut to previous) -┌─────────┬─────────────────────────────────────────────────────────────────────────┬──────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ -│ (index) │ scenario │ models_absolute_diff │ elements_absolute_diff │ conditions_absolute_diff │ technology_assignments_absolute_diff │ lines_of_code_absolute_diff │ -├─────────┼─────────────────────────────────────────────────────────────────────────┼──────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ -│ 0 │ 'EDMM Total Maintenance - EDMM Total' │ 1 │ 78 │ 0 │ 13 │ 233 │ -│ 1 │ 'VDMM Baseline Maintenance - VDMM Baseline Default' │ 0 │ 84 │ 15 │ 12 │ 205 │ -│ 2 │ 'VDMM+ Maintenance Manual - VDMM+ Default Manual' │ 0 │ 27 │ 17 │ 12 │ 90 │ -│ 3 │ 'VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality' │ 0 │ 27 │ 5 │ 0 │ 68 │ -└─────────┴─────────────────────────────────────────────────────────────────────────┴──────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ - -From Default to Maintained (Relative to change to baseline) -┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ -│ (index) │ scenario │ elements_relative_diff │ conditions_relative_diff │ technology_assignments_relative_diff │ lines_of_code_relative_diff │ -├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ -│ 0 │ '(VDMM+ Maintenance Manual - VDMM+ Default Manual) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.32 │ 1.13 │ 1 │ 0.44 │ -│ 1 │ '(VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.32 │ 0.33 │ 0 │ 0.33 │ -└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ - -> Diff: connection properties \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-004.txt b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-004.txt deleted file mode 100644 index 9dff403f4d..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-004.txt +++ /dev/null @@ -1,106 +0,0 @@ - -The technology rules of our case study. Qualities range from bad (0) to good (1). -┌─────────┬──────────────┬────────────────────────┬─────────────────────────────────────────────┬─────────┐ -│ (index) │ Technology │ Component │ Hosting │ Quality │ -├─────────┼──────────────┼────────────────────────┼─────────────────────────────────────────────┼─────────┤ -│ 0 │ 'ansible' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ -│ 1 │ 'ansible' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ -│ 2 │ 'ansible' │ 'software.application' │ [ 'gcp.appengine' ] │ 0 │ -│ 3 │ 'ansible' │ 'software.application' │ [ 'openstack.machine' ] │ 1 │ -│ 4 │ 'ansible' │ 'docker.engine' │ [ 'openstack.machine' ] │ 1 │ -│ 5 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ -│ 6 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ -│ 7 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ -│ 8 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ -│ 9 │ 'ansible' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 1 │ -│ 10 │ 'ansible' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ -│ 11 │ 'ansible' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ -│ 12 │ 'ansible' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ -│ 13 │ 'ansible' │ 'ingress' │ [ 'openstack.machine' ] │ 1 │ -│ 14 │ 'ansible' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ -│ 15 │ 'ansible' │ 'openstack.machine' │ undefined │ 0.5 │ -│ 16 │ 'ansible' │ 'gcp.service' │ undefined │ 1 │ -│ 17 │ 'terraform' │ 'software.application' │ [ 'software.runtime', 'openstack.machine' ] │ 0 │ -│ 18 │ 'terraform' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ -│ 19 │ 'terraform' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ -│ 20 │ 'terraform' │ 'software.application' │ [ 'gcp.appengine' ] │ 1 │ -│ 21 │ 'terraform' │ 'software.application' │ [ 'openstack.machine' ] │ 0 │ -│ 22 │ 'terraform' │ 'docker.engine' │ [ 'openstack.machine' ] │ 0 │ -│ 23 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ -│ 24 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ -│ 25 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ -│ 26 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ -│ 27 │ 'terraform' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 0 │ -│ 28 │ 'terraform' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ -│ 29 │ 'terraform' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ -│ 30 │ 'terraform' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ -│ 31 │ 'terraform' │ 'ingress' │ [ 'openstack.machine' ] │ 0 │ -│ 32 │ 'terraform' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ -│ 33 │ 'terraform' │ 'openstack.machine' │ undefined │ 1 │ -│ 34 │ 'terraform' │ 'gcp.service' │ undefined │ 1 │ -│ 35 │ 'kubernetes' │ 'software.application' │ [ 'kubernetes' ] │ 1 │ -│ 36 │ 'kubernetes' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 0 │ -│ 37 │ 'kubernetes' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 1 │ -│ 38 │ 'kubernetes' │ 'ingress' │ [ 'kubernetes' ] │ 1 │ -│ 39 │ 'docker' │ 'software.application' │ [ 'docker.engine' ] │ 1 │ -│ 40 │ 'docker' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 0 │ -│ 41 │ 'docker' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 1 │ -└─────────┴──────────────┴────────────────────────┴─────────────────────────────────────────────┴─────────┘ - -Metrics relevant when modeling the different scenarios -┌─────────┬────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────┐ -│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ -├─────────┼────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────┤ -│ 0 │ 'EDMM GCP Variant' │ 1 │ 84 │ 0 │ 14 │ 253 │ │ -│ 1 │ 'EDMM OS Large Variant' │ 1 │ 114 │ 0 │ 18 │ 318 │ │ -│ 2 │ 'EDMM OS Medium Variant' │ 1 │ 114 │ 0 │ 18 │ 318 │ │ -│ 3 │ 'EDMM Total (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant)' │ 3 │ 312 │ 0 │ 50 │ 889 │ 'EDMM Total' │ -│ 4 │ 'VDMM Baseline Default' │ 1 │ 193 │ 8 │ 31 │ 520 │ │ -│ 5 │ 'VDMM+ Default Manual' │ 1 │ 147 │ 47 │ 31 │ 477 │ │ -│ 6 │ 'VDMM+ Default Automated Random' │ 1 │ 147 │ 24 │ 0 │ 415 │ │ -│ 7 │ 'VDMM+ Default Automated Counting' │ 1 │ 147 │ 24 │ 0 │ 416 │ │ -│ 8 │ 'VDMM+ Default Automated Quality' │ 1 │ 147 │ 24 │ 0 │ 412 │ │ -└─────────┴────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────┘ - -Qualities of the derived deployment models, i.e., the deployment variants, of the different scenarios ranging from bad (0) to good (1). -┌─────────┬──────────────┬────────┬─────────────┬─────────────┬────────────────┬─────────┬──────────────────┐ -│ (index) │ scenario │ expert │ non_expert │ random │ counting │ quality │ quality_counting │ -├─────────┼──────────────┼────────┼─────────────┼─────────────┼────────────────┼─────────┼──────────────────┤ -│ 0 │ 'gcp' │ 1 │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ [ 0.29, 1 ] │ 1 │ 1 │ -│ 1 │ 'kubernetes' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.92 ] │ 1 │ 1 │ -│ 2 │ 'os-large' │ 1 │ [ 0.33, 1 ] │ [ 0.33, 1 ] │ [ 0.42, 0.67 ] │ 1 │ 1 │ -│ 3 │ 'os-medium' │ 1 │ [ 0.33, 1 ] │ [ 0.33, 1 ] │ [ 0.42, 0.67 ] │ 1 │ 1 │ -└─────────┴──────────────┴────────┴─────────────┴─────────────┴────────────────┴─────────┴──────────────────┘ - -Metrics relevant when modeling the maintenance scenario of our case study -┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────────────────┐ -│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ -├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────────────────┤ -│ 0 │ 'EDMM Kubernetes' │ 1 │ 88 │ 0 │ 13 │ 258 │ │ -│ 1 │ 'EDMM Total Maintenance (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant, EDMM Kubernetes)' │ 4 │ 400 │ 0 │ 63 │ 1147 │ 'EDMM Total Maintenance' │ -│ 2 │ 'VDMM Baseline Maintenance' │ 1 │ 287 │ 23 │ 43 │ 751 │ │ -│ 3 │ 'VDMM+ Maintenance Manual' │ 1 │ 174 │ 74 │ 43 │ 568 │ │ -│ 4 │ 'VDMM+ Maintenance Automated Random' │ 1 │ 174 │ 39 │ 0 │ 483 │ │ -│ 5 │ 'VDMM+ Maintenance Automated Counting' │ 1 │ 174 │ 39 │ 0 │ 484 │ │ -│ 6 │ 'VDMM+ Maintenance Automated Quality' │ 1 │ 174 │ 39 │ 0 │ 480 │ │ -└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────────────────┘ - -From Default to Maintained (Absolut to previous) -┌─────────┬─────────────────────────────────────────────────────────────────────────┬──────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ -│ (index) │ scenario │ models_absolute_diff │ elements_absolute_diff │ conditions_absolute_diff │ technology_assignments_absolute_diff │ lines_of_code_absolute_diff │ -├─────────┼─────────────────────────────────────────────────────────────────────────┼──────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ -│ 0 │ 'EDMM Total Maintenance - EDMM Total' │ 1 │ 88 │ 0 │ 13 │ 258 │ -│ 1 │ 'VDMM Baseline Maintenance - VDMM Baseline Default' │ 0 │ 94 │ 15 │ 12 │ 231 │ -│ 2 │ 'VDMM+ Maintenance Manual - VDMM+ Default Manual' │ 0 │ 27 │ 27 │ 12 │ 91 │ -│ 3 │ 'VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality' │ 0 │ 27 │ 15 │ 0 │ 68 │ -└─────────┴─────────────────────────────────────────────────────────────────────────┴──────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ - -From Default to Maintained (Relative to change to baseline) -┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ -│ (index) │ scenario │ elements_relative_diff │ conditions_relative_diff │ technology_assignments_relative_diff │ lines_of_code_relative_diff │ -├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ -│ 0 │ '(VDMM+ Maintenance Manual - VDMM+ Default Manual) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.29 │ 1.8 │ 1 │ 0.39 │ -│ 1 │ '(VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.29 │ 1 │ 0 │ 0.29 │ -└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ - -> Diff: artifacts \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-005.txt b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-005.txt deleted file mode 100644 index f808f636d0..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-005.txt +++ /dev/null @@ -1,107 +0,0 @@ - -The technology rules of our case study. Qualities range from bad (0) to good (1). -┌─────────┬──────────────┬────────────────────────┬─────────────────────────────────────────────┬─────────┐ -│ (index) │ Technology │ Component │ Hosting │ Quality │ -├─────────┼──────────────┼────────────────────────┼─────────────────────────────────────────────┼─────────┤ -│ 0 │ 'ansible' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ -│ 1 │ 'ansible' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ -│ 2 │ 'ansible' │ 'software.application' │ [ 'gcp.appengine' ] │ 0 │ -│ 3 │ 'ansible' │ 'software.application' │ [ 'openstack.machine' ] │ 1 │ -│ 4 │ 'ansible' │ 'docker.engine' │ [ 'openstack.machine' ] │ 1 │ -│ 5 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ -│ 6 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ -│ 7 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ -│ 8 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ -│ 9 │ 'ansible' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 1 │ -│ 10 │ 'ansible' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ -│ 11 │ 'ansible' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ -│ 12 │ 'ansible' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ -│ 13 │ 'ansible' │ 'ingress' │ [ 'openstack.machine' ] │ 1 │ -│ 14 │ 'ansible' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ -│ 15 │ 'ansible' │ 'openstack.machine' │ undefined │ 0.5 │ -│ 16 │ 'ansible' │ 'gcp.service' │ undefined │ 1 │ -│ 17 │ 'terraform' │ 'software.application' │ [ 'software.runtime', 'openstack.machine' ] │ 0 │ -│ 18 │ 'terraform' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ -│ 19 │ 'terraform' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ -│ 20 │ 'terraform' │ 'software.application' │ [ 'gcp.appengine' ] │ 1 │ -│ 21 │ 'terraform' │ 'software.application' │ [ 'openstack.machine' ] │ 0 │ -│ 22 │ 'terraform' │ 'docker.engine' │ [ 'openstack.machine' ] │ 0 │ -│ 23 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ -│ 24 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ -│ 25 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ -│ 26 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ -│ 27 │ 'terraform' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 0 │ -│ 28 │ 'terraform' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ -│ 29 │ 'terraform' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ -│ 30 │ 'terraform' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ -│ 31 │ 'terraform' │ 'ingress' │ [ 'openstack.machine' ] │ 0 │ -│ 32 │ 'terraform' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ -│ 33 │ 'terraform' │ 'openstack.machine' │ undefined │ 1 │ -│ 34 │ 'terraform' │ 'gcp.service' │ undefined │ 1 │ -│ 35 │ 'kubernetes' │ 'software.application' │ [ 'kubernetes' ] │ 1 │ -│ 36 │ 'kubernetes' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 0 │ -│ 37 │ 'kubernetes' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 1 │ -│ 38 │ 'kubernetes' │ 'ingress' │ [ 'kubernetes' ] │ 1 │ -│ 39 │ 'docker' │ 'software.application' │ [ 'docker.engine' ] │ 1 │ -│ 40 │ 'docker' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 0 │ -│ 41 │ 'docker' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 1 │ -└─────────┴──────────────┴────────────────────────┴─────────────────────────────────────────────┴─────────┘ - -Metrics relevant when modeling the different scenarios -┌─────────┬────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────┐ -│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ -├─────────┼────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────┤ -│ 0 │ 'EDMM GCP Variant' │ 1 │ 59 │ 0 │ 14 │ 205 │ │ -│ 1 │ 'EDMM OS Large Variant' │ 1 │ 88 │ 0 │ 18 │ 267 │ │ -│ 2 │ 'EDMM OS Medium Variant' │ 1 │ 88 │ 0 │ 18 │ 267 │ │ -│ 3 │ 'EDMM Total (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant)' │ 3 │ 235 │ 0 │ 50 │ 739 │ 'EDMM Total' │ -│ 4 │ 'VDMM Baseline Default' │ 1 │ 146 │ 16 │ 31 │ 450 │ │ -│ 5 │ 'VDMM+ Default Manual' │ 1 │ 113 │ 31 │ 31 │ 406 │ │ -│ 6 │ 'VDMM+ Default Automated Random' │ 1 │ 113 │ 8 │ 0 │ 344 │ │ -│ 7 │ 'VDMM+ Default Automated Counting' │ 1 │ 113 │ 8 │ 0 │ 345 │ │ -│ 8 │ 'VDMM+ Default Automated Quality' │ 1 │ 113 │ 8 │ 0 │ 341 │ │ -└─────────┴────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────┘ - -Qualities of the derived deployment models, i.e., the deployment variants, of the different scenarios ranging from bad (0) to good (1). -┌─────────┬──────────────┬────────┬─────────────┬─────────────┬────────────────┬─────────┬──────────────────┐ -│ (index) │ scenario │ expert │ non_expert │ random │ counting │ quality │ quality_counting │ -├─────────┼──────────────┼────────┼─────────────┼─────────────┼────────────────┼─────────┼──────────────────┤ -│ 0 │ 'gcp' │ 1 │ [ 0.27, 1 ] │ [ 0.27, 1 ] │ [ 0.27, 1 ] │ 1 │ 1 │ -│ 1 │ 'kubernetes' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.93 ] │ 1 │ 1 │ -│ 2 │ 'os-large' │ 1 │ [ 0.34, 1 ] │ [ 0.34, 1 ] │ [ 0.42, 0.66 ] │ 1 │ 1 │ -│ 3 │ 'os-medium' │ 1 │ [ 0.34, 1 ] │ [ 0.34, 1 ] │ [ 0.42, 0.66 ] │ 1 │ 1 │ -└─────────┴──────────────┴────────┴─────────────┴─────────────┴────────────────┴─────────┴──────────────────┘ - -Metrics relevant when modeling the maintenance scenario of our case study -┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────────────────┐ -│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ -├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────────────────┤ -│ 0 │ 'EDMM Kubernetes' │ 1 │ 68 │ 0 │ 13 │ 224 │ │ -│ 1 │ 'EDMM Total Maintenance (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant, EDMM Kubernetes)' │ 4 │ 303 │ 0 │ 63 │ 963 │ 'EDMM Total Maintenance' │ -│ 2 │ 'VDMM Baseline Maintenance' │ 1 │ 228 │ 35 │ 46 │ 671 │ │ -│ 3 │ 'VDMM+ Maintenance Manual' │ 1 │ 146 │ 51 │ 46 │ 519 │ │ -│ 4 │ 'VDMM+ Maintenance Automated Random' │ 1 │ 146 │ 13 │ 0 │ 428 │ │ -│ 5 │ 'VDMM+ Maintenance Automated Counting' │ 1 │ 146 │ 13 │ 0 │ 429 │ │ -│ 6 │ 'VDMM+ Maintenance Automated Quality' │ 1 │ 146 │ 13 │ 0 │ 425 │ │ -└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────────────────┘ - -From Default to Maintained (Absolut to previous) -┌─────────┬─────────────────────────────────────────────────────────────────────────┬──────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ -│ (index) │ scenario │ models_absolute_diff │ elements_absolute_diff │ conditions_absolute_diff │ technology_assignments_absolute_diff │ lines_of_code_absolute_diff │ -├─────────┼─────────────────────────────────────────────────────────────────────────┼──────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ -│ 0 │ 'EDMM Total Maintenance - EDMM Total' │ 1 │ 68 │ 0 │ 13 │ 224 │ -│ 1 │ 'VDMM Baseline Maintenance - VDMM Baseline Default' │ 0 │ 82 │ 19 │ 15 │ 221 │ -│ 2 │ 'VDMM+ Maintenance Manual - VDMM+ Default Manual' │ 0 │ 33 │ 20 │ 15 │ 113 │ -│ 3 │ 'VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality' │ 0 │ 33 │ 5 │ 0 │ 84 │ -└─────────┴─────────────────────────────────────────────────────────────────────────┴──────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ - -From Default to Maintained (Relative to change to baseline) -┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ -│ (index) │ scenario │ elements_relative_diff │ conditions_relative_diff │ technology_assignments_relative_diff │ lines_of_code_relative_diff │ -├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ -│ 0 │ '(VDMM+ Maintenance Manual - VDMM+ Default Manual) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.4 │ 1.05 │ 1 │ 0.51 │ -│ 1 │ '(VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.4 │ 0.26 │ 0 │ 0.38 │ -└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ - -> Starting Point: Docker on VM; Diff: payment properties already in default and new analytical component with analytical properties in maintenance -> CURRENTLY SELECTED \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-006.txt b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-006.txt deleted file mode 100644 index 1d00aa1024..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-006.txt +++ /dev/null @@ -1,107 +0,0 @@ - -The technology rules of our case study. Qualities range from bad (0) to good (1). -┌─────────┬──────────────┬────────────────────────┬─────────────────────────────────────────────┬─────────┐ -│ (index) │ Technology │ Component │ Hosting │ Quality │ -├─────────┼──────────────┼────────────────────────┼─────────────────────────────────────────────┼─────────┤ -│ 0 │ 'ansible' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ -│ 1 │ 'ansible' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ -│ 2 │ 'ansible' │ 'software.application' │ [ 'gcp.appengine' ] │ 0 │ -│ 3 │ 'ansible' │ 'software.application' │ [ 'openstack.machine' ] │ 1 │ -│ 4 │ 'ansible' │ 'docker.engine' │ [ 'openstack.machine' ] │ 1 │ -│ 5 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ -│ 6 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ -│ 7 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ -│ 8 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ -│ 9 │ 'ansible' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 1 │ -│ 10 │ 'ansible' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ -│ 11 │ 'ansible' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ -│ 12 │ 'ansible' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ -│ 13 │ 'ansible' │ 'ingress' │ [ 'openstack.machine' ] │ 1 │ -│ 14 │ 'ansible' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ -│ 15 │ 'ansible' │ 'openstack.machine' │ undefined │ 0.5 │ -│ 16 │ 'ansible' │ 'gcp.service' │ undefined │ 1 │ -│ 17 │ 'terraform' │ 'software.application' │ [ 'software.runtime', 'openstack.machine' ] │ 0 │ -│ 18 │ 'terraform' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ -│ 19 │ 'terraform' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ -│ 20 │ 'terraform' │ 'software.application' │ [ 'gcp.appengine' ] │ 1 │ -│ 21 │ 'terraform' │ 'software.application' │ [ 'openstack.machine' ] │ 0 │ -│ 22 │ 'terraform' │ 'docker.engine' │ [ 'openstack.machine' ] │ 0 │ -│ 23 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ -│ 24 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ -│ 25 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ -│ 26 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ -│ 27 │ 'terraform' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 0 │ -│ 28 │ 'terraform' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ -│ 29 │ 'terraform' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ -│ 30 │ 'terraform' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ -│ 31 │ 'terraform' │ 'ingress' │ [ 'openstack.machine' ] │ 0 │ -│ 32 │ 'terraform' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ -│ 33 │ 'terraform' │ 'openstack.machine' │ undefined │ 1 │ -│ 34 │ 'terraform' │ 'gcp.service' │ undefined │ 1 │ -│ 35 │ 'kubernetes' │ 'software.application' │ [ 'kubernetes' ] │ 1 │ -│ 36 │ 'kubernetes' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 0 │ -│ 37 │ 'kubernetes' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 1 │ -│ 38 │ 'kubernetes' │ 'ingress' │ [ 'kubernetes' ] │ 1 │ -│ 39 │ 'docker' │ 'software.application' │ [ 'docker.engine' ] │ 1 │ -│ 40 │ 'docker' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 0 │ -│ 41 │ 'docker' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 1 │ -└─────────┴──────────────┴────────────────────────┴─────────────────────────────────────────────┴─────────┘ - -Metrics relevant when modeling the different scenarios -┌─────────┬────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────┐ -│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ -├─────────┼────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────┤ -│ 0 │ 'EDMM GCP Variant' │ 1 │ 63 │ 0 │ 14 │ 211 │ │ -│ 1 │ 'EDMM OS Large Variant' │ 1 │ 92 │ 0 │ 18 │ 273 │ │ -│ 2 │ 'EDMM OS Medium Variant' │ 1 │ 92 │ 0 │ 18 │ 273 │ │ -│ 3 │ 'EDMM Total (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant)' │ 3 │ 247 │ 0 │ 50 │ 757 │ 'EDMM Total' │ -│ 4 │ 'VDMM Baseline Default' │ 1 │ 154 │ 16 │ 31 │ 462 │ │ -│ 5 │ 'VDMM+ Default Manual' │ 1 │ 117 │ 31 │ 31 │ 412 │ │ -│ 6 │ 'VDMM+ Default Automated Random' │ 1 │ 117 │ 8 │ 0 │ 350 │ │ -│ 7 │ 'VDMM+ Default Automated Counting' │ 1 │ 117 │ 8 │ 0 │ 351 │ │ -│ 8 │ 'VDMM+ Default Automated Quality' │ 1 │ 117 │ 8 │ 0 │ 347 │ │ -└─────────┴────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────┘ - -Qualities of the derived deployment models, i.e., the deployment variants, of the different scenarios ranging from bad (0) to good (1). -┌─────────┬──────────────┬────────┬─────────────┬─────────────┬────────────────┬─────────┬──────────────────┐ -│ (index) │ scenario │ expert │ non_expert │ random │ counting │ quality │ quality_counting │ -├─────────┼──────────────┼────────┼─────────────┼─────────────┼────────────────┼─────────┼──────────────────┤ -│ 0 │ 'gcp' │ 1 │ [ 0.27, 1 ] │ [ 0.27, 1 ] │ [ 0.27, 1 ] │ 1 │ 1 │ -│ 1 │ 'kubernetes' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.93 ] │ 1 │ 1 │ -│ 2 │ 'os-large' │ 1 │ [ 0.34, 1 ] │ [ 0.34, 1 ] │ [ 0.42, 0.66 ] │ 1 │ 1 │ -│ 3 │ 'os-medium' │ 1 │ [ 0.34, 1 ] │ [ 0.34, 1 ] │ [ 0.42, 0.66 ] │ 1 │ 1 │ -└─────────┴──────────────┴────────┴─────────────┴─────────────┴────────────────┴─────────┴──────────────────┘ - -Metrics relevant when modeling the maintenance scenario of our case study -┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────────────────┐ -│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ -├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────────────────┤ -│ 0 │ 'EDMM Kubernetes' │ 1 │ 72 │ 0 │ 13 │ 230 │ │ -│ 1 │ 'EDMM Total Maintenance (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant, EDMM Kubernetes)' │ 4 │ 319 │ 0 │ 63 │ 987 │ 'EDMM Total Maintenance' │ -│ 2 │ 'VDMM Baseline Maintenance' │ 1 │ 240 │ 35 │ 46 │ 689 │ │ -│ 3 │ 'VDMM+ Maintenance Manual' │ 1 │ 150 │ 51 │ 46 │ 525 │ │ -│ 4 │ 'VDMM+ Maintenance Automated Random' │ 1 │ 150 │ 13 │ 0 │ 434 │ │ -│ 5 │ 'VDMM+ Maintenance Automated Counting' │ 1 │ 150 │ 13 │ 0 │ 435 │ │ -│ 6 │ 'VDMM+ Maintenance Automated Quality' │ 1 │ 150 │ 13 │ 0 │ 431 │ │ -└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────────────────┘ - -From Default to Maintained (Absolut to previous) -┌─────────┬─────────────────────────────────────────────────────────────────────────┬──────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ -│ (index) │ scenario │ models_absolute_diff │ elements_absolute_diff │ conditions_absolute_diff │ technology_assignments_absolute_diff │ lines_of_code_absolute_diff │ -├─────────┼─────────────────────────────────────────────────────────────────────────┼──────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ -│ 0 │ 'EDMM Total Maintenance - EDMM Total' │ 1 │ 72 │ 0 │ 13 │ 230 │ -│ 1 │ 'VDMM Baseline Maintenance - VDMM Baseline Default' │ 0 │ 86 │ 19 │ 15 │ 227 │ -│ 2 │ 'VDMM+ Maintenance Manual - VDMM+ Default Manual' │ 0 │ 33 │ 20 │ 15 │ 113 │ -│ 3 │ 'VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality' │ 0 │ 33 │ 5 │ 0 │ 84 │ -└─────────┴─────────────────────────────────────────────────────────────────────────┴──────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ - -From Default to Maintained (Relative to change to baseline) -┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────────┬──────────────────────────┬──────────────────────────────────────┬─────────────────────────────┐ -│ (index) │ scenario │ elements_relative_diff │ conditions_relative_diff │ technology_assignments_relative_diff │ lines_of_code_relative_diff │ -├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────┼──────────────────────────┼──────────────────────────────────────┼─────────────────────────────┤ -│ 0 │ '(VDMM+ Maintenance Manual - VDMM+ Default Manual) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.38 │ 1.05 │ 1 │ 0.5 │ -│ 1 │ '(VDMM+ Maintenance Automated Quality - VDMM+ Default Automated Quality) / (VDMM Baseline Maintenance - VDMM Baseline Default)' │ 0.38 │ 0.26 │ 0 │ 0.37 │ -└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────┴──────────────────────────┴──────────────────────────────────────┴─────────────────────────────┘ - -> Starting Point: 005; Diff: payment properties also at frontend and checkout -> Comment: little value, configuration should happen automatically due to specialized tosca node types \ No newline at end of file diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-007.txt b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-007.txt deleted file mode 100644 index c9a4a01dcf..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study-007.txt +++ /dev/null @@ -1,116 +0,0 @@ - -The technology rules of our case study. Qualities range from bad (0) to good (1). -┌─────────┬──────────────┬────────────────────────┬───────────────────────────────────────┬─────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ (index) │ Technology │ Component │ Hosting │ Quality │ Comment │ -├─────────┼──────────────┼────────────────────────┼───────────────────────────────────────┼─────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ -│ 0 │ 'ansible' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ 'Docker is more specialized.' │ -│ 1 │ 'ansible' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ 'Kubernetes is more specialized.' │ -│ 2 │ 'ansible' │ 'software.application' │ [ 'gcp.cloudrun' ] │ 0 │ 'Custom module with imperative parts, while Terraform provides a declarative module.' │ -│ 3 │ 'ansible' │ 'software.application' │ [ 'openstack.machine' ] │ 1 │ 'Primary use case due to the specialization of Ansible.' │ -│ 4 │ 'ansible' │ 'docker.engine' │ [ 'openstack.machine' ] │ 1 │ 'Primary use case due to the specialization of Ansible.' │ -│ 5 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ 'Primary use case due to the specialization of Ansible.' │ -│ 6 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ 'Primary use case due to the specialization of Ansible.' │ -│ 7 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ 'Primary use case due to the specialization of Ansible.' │ -│ 8 │ 'ansible' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ undefined │ -│ 9 │ 'ansible' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 1 │ 'Primary use case due to the specialization of Ansible.' │ -│ 10 │ 'ansible' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ 'Docker is more specialized.' │ -│ 11 │ 'ansible' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ 'Kubernetes is more specialized.' │ -│ 12 │ 'ansible' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ undefined │ -│ 13 │ 'ansible' │ 'ingress' │ [ 'openstack.machine' ] │ 1 │ 'Primary use case due to the specialization of Ansible.' │ -│ 14 │ 'ansible' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ 'Kubernetes is more specialized.' │ -│ 15 │ 'ansible' │ 'openstack.machine' │ undefined │ 0.5 │ 'Terraform is more specialized.' │ -│ 16 │ 'ansible' │ 'gcp.service' │ undefined │ 1 │ undefined │ -│ 17 │ 'terraform' │ 'software.application' │ [ 'docker.engine' ] │ 0.5 │ 'Docker is more specialized.' │ -│ 18 │ 'terraform' │ 'software.application' │ [ 'kubernetes' ] │ 0.5 │ 'Kubernetes is more specialized.' │ -│ 19 │ 'terraform' │ 'software.application' │ [ 'gcp.cloudrun' ] │ 1 │ 'Terraform provides a declarative module.' │ -│ 20 │ 'terraform' │ 'software.application' │ [ 'openstack.machine' ] │ 0 │ 'Ansible is more specialized. Also using Remote-Exec Executor is a "last resort".' │ -│ 21 │ 'terraform' │ 'docker.engine' │ [ 'openstack.machine' ] │ 0 │ 'Ansible is more specialized. Also using Remote-Exec Executor is a "last resort".' │ -│ 22 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'openstack.machine' ] │ 1 │ 'Terraform provides a declarative module.' │ -│ 23 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 1 │ 'Terraform provides a declarative module.' │ -│ 24 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 1 │ 'Terraform provides a declarative module.' │ -│ 25 │ 'terraform' │ 'mysql.database' │ [ 'mysql.dbms', 'gcp.cloudsql' ] │ 1 │ 'Terraform provides a declarative module.' │ -│ 26 │ 'terraform' │ 'mysql.dbms' │ [ 'openstack.machine' ] │ 0 │ 'Ansible is more specialized. Also using Remote-Exec Executor is a "last resort".' │ -│ 27 │ 'terraform' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 0.5 │ 'Docker is more specialized.' │ -│ 28 │ 'terraform' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 0.5 │ 'Kubernetes is more specialized.' │ -│ 29 │ 'terraform' │ 'mysql.dbms' │ [ 'gcp.cloudsql' ] │ 1 │ 'Terraform provides a declarative module.' │ -│ 30 │ 'terraform' │ 'ingress' │ [ 'openstack.machine' ] │ 0 │ 'Ansible is more specialized. Also using Remote-Exec Executor is a "last resort".' │ -│ 31 │ 'terraform' │ 'ingress' │ [ 'kubernetes' ] │ 0.5 │ 'Kubernetes is more specialized.' │ -│ 32 │ 'terraform' │ 'openstack.machine' │ undefined │ 1 │ 'Terraform provides a declarative module.' │ -│ 33 │ 'terraform' │ 'gcp.service' │ undefined │ 1 │ 'Terraform provides a declarative module.' │ -│ 34 │ 'kubernetes' │ 'software.application' │ [ 'kubernetes' ] │ 1 │ 'Kubernetes is the underlying technology.' │ -│ 35 │ 'kubernetes' │ 'mysql.database' │ [ 'mysql.dbms', 'kubernetes' ] │ 0 │ 'Kubernetes Job with imperative parts, while declarative other technologies provide declarative modules.' │ -│ 36 │ 'kubernetes' │ 'mysql.dbms' │ [ 'kubernetes' ] │ 1 │ 'Kubernetes is the underlying technology.' │ -│ 37 │ 'kubernetes' │ 'ingress' │ [ 'kubernetes' ] │ 1 │ 'Kubernetes is the underlying technology.' │ -│ 38 │ 'docker' │ 'software.application' │ [ 'docker.engine' ] │ 1 │ 'Docker is the underlying technology.' │ -│ 39 │ 'docker' │ 'mysql.database' │ [ 'mysql.dbms', 'docker.engine' ] │ 0 │ 'One-time use docker container ("fake Kubernetes job") with imperative parts, while declarative other technologies provide declarative modules.' │ -│ 40 │ 'docker' │ 'mysql.dbms' │ [ 'docker.engine' ] │ 1 │ 'Docker is the underlying technology.' │ -└─────────┴──────────────┴────────────────────────┴───────────────────────────────────────┴─────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - -Metrics relevant when modeling the different scenarios -┌─────────┬────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────┐ -│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ -├─────────┼────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────┤ -│ 0 │ 'EDMM GCP Variant' │ 1 │ 59 │ 0 │ 14 │ 205 │ │ -│ 1 │ 'EDMM OS Large Variant' │ 1 │ 88 │ 0 │ 18 │ 267 │ │ -│ 2 │ 'EDMM OS Medium Variant' │ 1 │ 88 │ 0 │ 18 │ 267 │ │ -│ 3 │ 'EDMM Total (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant)' │ 3 │ 235 │ 0 │ 50 │ 739 │ 'EDMM Total' │ -│ 4 │ 'VDMM Baseline Original' │ 1 │ 146 │ 16 │ 31 │ 450 │ │ -│ 5 │ 'VDMM+ Original Manual' │ 1 │ 113 │ 31 │ 31 │ 406 │ │ -│ 6 │ 'VDMM+ Original Automated Random' │ 1 │ 113 │ 8 │ 0 │ 344 │ │ -│ 7 │ 'VDMM+ Original Automated Counting' │ 1 │ 113 │ 8 │ 0 │ 345 │ │ -│ 8 │ 'VDMM+ Original Automated Quality' │ 1 │ 113 │ 8 │ 0 │ 341 │ │ -└─────────┴────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────┘ - -Diff when modeling the different original scenarios -┌─────────┬──────────────────────────────────────────────────────────────┬─────────────────┬─────────────────┬───────────────────┬───────────────────┬─────────────────────┬─────────────────────┬─────────────────────────────────┬─────────────────────────────────┬────────────────────────┬────────────────────────┐ -│ (index) │ scenario │ models_abs_diff │ models_rel_diff │ elements_abs_diff │ elements_rel_diff │ conditions_abs_diff │ conditions_rel_diff │ technology_assignments_abs_diff │ technology_assignments_rel_diff │ lines_of_code_abs_diff │ lines_of_code_rel_diff │ -├─────────┼──────────────────────────────────────────────────────────────┼─────────────────┼─────────────────┼───────────────────┼───────────────────┼─────────────────────┼─────────────────────┼─────────────────────────────────┼─────────────────────────────────┼────────────────────────┼────────────────────────┤ -│ 0 │ 'VDMM Baseline Original - EDMM Total' │ -2 │ 0.33 │ -89 │ 0.62 │ 16 │ Infinity │ -19 │ 0.62 │ -289 │ 0.61 │ -│ 1 │ 'VDMM+ Original Manual - VDMM Baseline Original' │ 0 │ 1 │ -33 │ 0.77 │ 15 │ 1.94 │ 0 │ 1 │ -44 │ 0.9 │ -│ 2 │ 'VDMM+ Original Automated Random - VDMM Baseline Original' │ 0 │ 1 │ -33 │ 0.77 │ -8 │ 0.5 │ -31 │ 0 │ -106 │ 0.76 │ -│ 3 │ 'VDMM+ Original Automated Counting - VDMM Baseline Original' │ 0 │ 1 │ -33 │ 0.77 │ -8 │ 0.5 │ -31 │ 0 │ -105 │ 0.77 │ -│ 4 │ 'VDMM+ Original Automated Quality - VDMM Baseline Original' │ 0 │ 1 │ -33 │ 0.77 │ -8 │ 0.5 │ -31 │ 0 │ -109 │ 0.76 │ -└─────────┴──────────────────────────────────────────────────────────────┴─────────────────┴─────────────────┴───────────────────┴───────────────────┴─────────────────────┴─────────────────────┴─────────────────────────────────┴─────────────────────────────────┴────────────────────────┴────────────────────────┘ - -Qualities of the derived deployment models, i.e., the deployment variants, of the different scenarios ranging from bad (0) to good (1). -┌─────────┬──────────────┬────────┬─────────────┬─────────────┬────────────────┬─────────┬──────────────────┐ -│ (index) │ scenario │ expert │ non_expert │ random │ counting │ quality │ quality_counting │ -├─────────┼──────────────┼────────┼─────────────┼─────────────┼────────────────┼─────────┼──────────────────┤ -│ 0 │ 'gcp' │ 1 │ [ 0.27, 1 ] │ [ 0.27, 1 ] │ [ 0.27, 1 ] │ 1 │ 1 │ -│ 1 │ 'kubernetes' │ 1 │ [ 0.46, 1 ] │ [ 0.46, 1 ] │ [ 0.54, 0.93 ] │ 1 │ 1 │ -│ 2 │ 'os-large' │ 1 │ [ 0.34, 1 ] │ [ 0.34, 1 ] │ [ 0.42, 0.66 ] │ 1 │ 1 │ -│ 3 │ 'os-medium' │ 1 │ [ 0.34, 1 ] │ [ 0.34, 1 ] │ [ 0.42, 0.66 ] │ 1 │ 1 │ -└─────────┴──────────────┴────────┴─────────────┴─────────────┴────────────────┴─────────┴──────────────────┘ - -Metrics relevant when modeling the maintenance scenario of our case study -┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬──────────┬────────────┬────────────────────────┬───────────────┬──────────────────────────┐ -│ (index) │ scenario │ models │ elements │ conditions │ technology_assignments │ lines_of_code │ short │ -├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼──────────┼────────────┼────────────────────────┼───────────────┼──────────────────────────┤ -│ 0 │ 'EDMM Kubernetes' │ 1 │ 68 │ 0 │ 13 │ 224 │ │ -│ 1 │ 'EDMM Total Maintenance (EDMM GCP Variant, EDMM OS Medium Variant, EDMM OS Large Variant, EDMM Kubernetes)' │ 4 │ 303 │ 0 │ 63 │ 963 │ 'EDMM Total Maintenance' │ -│ 2 │ 'VDMM Baseline Maintenance' │ 1 │ 228 │ 35 │ 46 │ 671 │ │ -│ 3 │ 'VDMM+ Maintenance Manual' │ 1 │ 146 │ 51 │ 46 │ 519 │ │ -│ 4 │ 'VDMM+ Maintenance Automated Random' │ 1 │ 146 │ 13 │ 0 │ 428 │ │ -│ 5 │ 'VDMM+ Maintenance Automated Counting' │ 1 │ 146 │ 13 │ 0 │ 429 │ │ -│ 6 │ 'VDMM+ Maintenance Automated Quality' │ 1 │ 146 │ 13 │ 0 │ 425 │ │ -└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴──────────┴────────────┴────────────────────────┴───────────────┴──────────────────────────┘ - -From Original to Maintained (Absolut to previous) (Absolute) -┌─────────┬──────────────────────────────────────────────────────────────────────────┬─────────────────┬───────────────────┬─────────────────────┬─────────────────────────────────┬────────────────────────┐ -│ (index) │ scenario │ models_abs_diff │ elements_abs_diff │ conditions_abs_diff │ technology_assignments_abs_diff │ lines_of_code_abs_diff │ -├─────────┼──────────────────────────────────────────────────────────────────────────┼─────────────────┼───────────────────┼─────────────────────┼─────────────────────────────────┼────────────────────────┤ -│ 0 │ 'EDMM Total Maintenance - EDMM Total' │ 1 │ 68 │ 0 │ 13 │ 224 │ -│ 1 │ 'VDMM Baseline Maintenance - VDMM Baseline Original' │ 0 │ 82 │ 19 │ 15 │ 221 │ -│ 2 │ 'VDMM+ Maintenance Manual - VDMM+ Original Manual' │ 0 │ 33 │ 20 │ 15 │ 113 │ -│ 3 │ 'VDMM+ Maintenance Automated Quality - VDMM+ Original Automated Quality' │ 0 │ 33 │ 5 │ 0 │ 84 │ -└─────────┴──────────────────────────────────────────────────────────────────────────┴─────────────────┴───────────────────┴─────────────────────┴─────────────────────────────────┴────────────────────────┘ - -From Original to Maintained (Relative to change to baseline) -┌─────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬───────────────────┬─────────────────────┬─────────────────────────────────┬────────────────────────┐ -│ (index) │ scenario │ elements_rel_diff │ conditions_rel_diff │ technology_assignments_rel_diff │ lines_of_code_rel_diff │ -├─────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────────┼─────────────────────┼─────────────────────────────────┼────────────────────────┤ -│ 0 │ '(VDMM+ Maintenance Manual - VDMM+ Original Manual) / (VDMM Baseline Maintenance - VDMM Baseline Original)' │ 0.4 │ 1.05 │ 1 │ 0.51 │ -│ 1 │ '(VDMM+ Maintenance Automated Quality - VDMM+ Original Automated Quality) / (VDMM Baseline Maintenance - VDMM Baseline Original)' │ 0.4 │ 0.26 │ 0 │ 0.38 │ -└─────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴───────────────────┴─────────────────────┴─────────────────────────────────┴────────────────────────┘ - -> 006 but with enriched data diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study.sh deleted file mode 100755 index d8b7a00971..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/study.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -set -e - -# Load configuration -source configuration.sh - -# Study -$VINTNER study technology --application boutique --experimental diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/swap-lib.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/swap-lib.sh deleted file mode 100755 index 3c6c742fdf..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/swap-lib.sh +++ /dev/null @@ -1,16 +0,0 @@ -#! /usr/bin/bash -set -e - -# Set working directory -cd "$(dirname "$0")" - -FS="/c/Users" -if [[ "${OSTYPE}" == "linux-gnu" ]]; then - FS="/home" -fi - -# Delete lib in instance -rm -rf ${FS}/stoetzms/.opentosca_vintner/instances/technology-gcp/data/ensemble/lib - -# Copy local lib into instance -cp -R ../lib ${FS}/stoetzms/.opentosca_vintner/instances/technology-gcp/data/ensemble diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/undeploy.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/undeploy.sh deleted file mode 100755 index 799765e670..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/undeploy.sh +++ /dev/null @@ -1,11 +0,0 @@ -#! /usr/bin/bash -set -e - -# Set working directory -cd "$(dirname "$0")" - -# Load configuration -source configuration.sh - -# Undeploy application -$VINTNER instances undeploy --instance ${TEMPLATE_NAME} diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/unimplement.sh b/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/unimplement.sh deleted file mode 100755 index f92b98c181..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/scripts/unimplement.sh +++ /dev/null @@ -1,9 +0,0 @@ -#! /usr/bin/bash -set -e - -# Load configuration -source configuration.sh - -# Pull dependencies -$VINTNER technologies clean --lib ${TEMPLATE_DIR}/lib - diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/study.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/study.yaml deleted file mode 100644 index 227ccb140c..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/study.yaml +++ /dev/null @@ -1,6 +0,0 @@ -study: technology -originals: - - customer - - development - - hyperscaler - - local diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/expected.yaml deleted file mode 100644 index 7f3f0f125b..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/expected.yaml +++ /dev/null @@ -1 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_3 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/inputs.yaml deleted file mode 100644 index 7bf937ccc5..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/customer/inputs.yaml +++ /dev/null @@ -1 +0,0 @@ -env: CUSTOMER diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/expected.yaml deleted file mode 100644 index 7f3f0f125b..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/expected.yaml +++ /dev/null @@ -1 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_3 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/inputs.yaml deleted file mode 100644 index 09169fd274..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/development/inputs.yaml +++ /dev/null @@ -1 +0,0 @@ -env: DEVELOPMENT diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/expected.yaml deleted file mode 100644 index 7f3f0f125b..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/expected.yaml +++ /dev/null @@ -1 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_3 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/inputs.yaml deleted file mode 100644 index 6fb22896df..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/hyperscaler/inputs.yaml +++ /dev/null @@ -1 +0,0 @@ -env: HYPERSCALER diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/expected.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/expected.yaml deleted file mode 100644 index 7f3f0f125b..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/expected.yaml +++ /dev/null @@ -1 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_3 diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/inputs.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/inputs.yaml deleted file mode 100644 index 4988a41091..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/tests/local/inputs.yaml +++ /dev/null @@ -1 +0,0 @@ -env: LOCAL diff --git a/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml b/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml deleted file mode 100644 index 17ec92db89..0000000000 --- a/examples/unfurl-technology---industry---plus-maintenance-automated/variable-service-template.yaml +++ /dev/null @@ -1,882 +0,0 @@ -tosca_definitions_version: tosca_variability_1_0_rc_3 - -imports: - - lib/types.yaml - -topology_template: - inputs: - retailer_name: - type: string - - global_service_gateway_endpoint: - type: string - - global_service_gateway_token: - type: string - - payment_provider_endpoint: - type: string - - payment_provider_token: - type: string - - coffee_provider_type: - type: string - conditions: {logic_expression: has_coffee} - - coffee_provider_endpoint: - type: string - conditions: {logic_expression: has_coffee} - - coffee_provider_token: - type: string - conditions: {logic_expression: has_coffee} - - os_network: - type: string - - os_ssh_key_name: - type: string - - os_ssh_user: - type: string - - os_ssh_key_file: - type: string - - os_region_name: - type: string - - os_auth_type: - type: string - - os_auth_url: - type: string - - os_identity_api_version: - type: string - - os_interface: - type: string - - os_application_credential_id: - type: string - - os_application_credential_secret: - type: string - - gcp_region: - type: string - - gcp_service_account_file: - type: string - - gcp_project: - type: string - - k8s_host: - type: string - - k8s_ca_cert_file: - type: string - - k8s_client_cert_file: - type: string - - k8s_client_key_file: - type: string - - variability: - expressions: - has_info_logging: {equal: [{variability_input: logging}, ERROR]} - has_debug_logging: {equal: [{variability_input: logging}, DEBUG]} - has_error_masking: {equal: [{variability_input: errors}, true]} - - has_coffee: {equal: [{variability_input: coffee}, true]} - - has_introspection: {equal: [{variability_input: introspection}, true]} - has_playground: {equal: [{variability_input: playground}, true]} - - has_import: {equal: [{variability_input: import}, true]} - has_import_schema_a: {equal: [{variability_input: import_schema}, A]} - has_import_schema_b: {equal: [{variability_input: import_schema}, B]} - - has_payment_merchant_a: {equal: [{variability_input: payment_merchant_a}, true]} - has_payment_merchant_b: {equal: [{variability_input: payment_merchant_b}, true]} - - is_hyperscaler: {equal: [{variability_input: env}, HYPERSCALER]} - is_local: {equal: [{variability_input: env}, LOCAL]} - is_customer: {equal: [{variability_input: env}, CUSTOMER]} - is_development: {equal: [{variability_input: env}, DEVELOPMENT]} - - # TODO: remove these - options: - #technology_constraint: false - #required_artifact_constraint: false - #expected_artifact_check: true - - inputs: - env: - type: string - default: DEVELOPMENT - - errors: - type: boolean - default: false - - logging: - type: string - default: INFO - - coffee: - type: boolean - default: false - - introspection: - type: boolean - default: false - - playground: - type: boolean - default: false - - import: - type: boolean - default: false - - import_schema: - type: string - default: A - - payment_merchant_a: - type: boolean - default: true - - payment_merchant_b: - type: boolean - default: true - - node_templates: - ################################################### - # - # Retailer Dashboard - # - ################################################### - - retailer_frontend_dashboard: - type: retailer.frontend.dashboard - properties: - - application_name: retailer-frontend-dashboard - - application_port: 3000 - - application_protocol: http - - logging_level: - value: info - conditions: {logic_expression: has_info_logging} - - - logging_level: - value: info - conditions: {logic_expression: has_debug_logging} - - - retailer_service_gateway_endpoint: {eval: '.::.requirements::[.name=retailer_service_gateway]::.target::application_endpoint'} - requirements: - - retailer_service_gateway: retailer_service_gateway - - host: local_docker_engine - - host: remote_docker_engine - - host: kubernetes_cluster - artifacts: - - docker_image: - type: docker.image - file: retailer.frontend.dashboard:vX.Y.Z - - retailer_ingress_dashboard: - type: ingress - requirements: - - application: retailer_frontend_dashboard - - host: virtual_machine - - host: kubernetes_cluster - - ################################################### - # - # Retailer Terminal - # - ################################################### - - retailer_frontend_terminal: - type: retailer.frontend.terminal - properties: - - application_name: retailer-frontend-terminal - - application_port: 3000 - - application_protocol: http - - logging_level: - value: info - conditions: {logic_expression: has_info_logging} - - - logging_level: - value: info - conditions: {logic_expression: has_debug_logging} - - - retailer_service_gateway_endpoint: {eval: '.::.requirements::[.name=retailer_service_gateway]::.target::application_endpoint'} - requirements: - - retailer_service_gateway: retailer_service_gateway - - host: local_docker_engine - - host: remote_docker_engine - - host: kubernetes_cluster - artifacts: - - docker_image: - type: docker.image - file: retailer.frontend.dashboard:vX.Y.Z - - retailer_ingress_terminal: - type: ingress - requirements: - - application: retailer_frontend_terminal - - host: virtual_machine - - host: kubernetes_cluster - - ################################################### - # - # Retailer Gateway - # - ################################################### - - retailer_service_gateway: - type: retailer.service.gateway - persistent: true - properties: - - application_name: retailer-service-gateway - - application_port: 4000 - - application_protocol: graphql - - - logging_level: - value: info - conditions: {logic_expression: has_info_logging} - - - logging_level: - value: info - conditions: {logic_expression: has_debug_logging} - - - retailer_name: {get_input: retailer_name} - - - graphql_introspection: - value: true - conditions: {logic_expression: has_introspection} - - - graphql_introspection: - value: false - conditions: {not: {logic_expression: has_introspection}} - - - graphql_playground: - value: true - conditions: {logic_expression: has_playground} - - - graphql_playground: - value: false - conditions: {not: {logic_expression: has_playground}} - - - has_error_masking: - value: true - conditions: {logic_expression: has_error_masking} - - - has_error_masking: - value: false - conditions: {not: {logic_expression: has_error_masking}} - - - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} - - retailer_service_core_endpoint: {eval: '.::.requirements::[.name=retailer_service_core]::.target::application_endpoint'} - - retailer_service_jobs_endpoint: {eval: '.::.requirements::[.name=retailer_service_jobs]::.target::application_endpoint'} - - retailer_service_stores_endpoint: {eval: '.::.requirements::[.name=retailer_service_stores]::.target::application_endpoint'} - - retailer_service_products_endpoint: {eval: '.::.requirements::[.name=retailer_service_products]::.target::application_endpoint'} - - retailer_service_stocks_endpoint: {eval: '.::.requirements::[.name=retailer_service_stocks]::.target::application_endpoint'} - - retailer_service_orders_endpoint: {eval: '.::.requirements::[.name=retailer_service_orders]::.target::application_endpoint'} - - retailer_service_global_endpoint: {eval: '.::.requirements::[.name=retailer_service_global]::.target::application_endpoint'} - requirements: - - retailer_service_core: retailer_service_core - - retailer_service_jobs: retailer_service_jobs - - retailer_service_stores: retailer_service_stores - - retailer_service_products: retailer_service_products - - retailer_service_stocks: retailer_service_stocks - - retailer_service_orders: retailer_service_orders - - retailer_service_global: retailer_service_global - - host: local_docker_engine - - host: remote_docker_engine - - host: kubernetes_cluster - artifacts: - - docker_image: - type: docker.image - file: retailer.service.gateway:vX.Y.Z - - retailer_ingress_gateway: - type: ingress - requirements: - - application: retailer_service_gateway - - host: virtual_machine - - host: kubernetes_cluster - - ################################################### - # - # Retailer Core - # - ################################################### - - retailer_service_core: - type: retailer.service.core - properties: - - application_name: retailer-service-core - - application_port: 4000 - - application_protocol: graphql - - logging_level: - value: info - conditions: {logic_expression: has_info_logging} - - - logging_level: - value: info - conditions: {logic_expression: has_debug_logging} - - - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} - - - coffee_enabled: - value: true - conditions: {logic_expression: has_coffee} - - - coffee_enabled: - value: false - conditions: {not: {logic_expression: has_coffee}} - - - coffee_provider_type: - value: {get_input: coffee_provider_type} - conditions: {logic_expression: has_coffee} - - - coffee_provider_endpoint: - value: {get_input: coffee_provider_endpoint} - conditions: {logic_expression: has_coffee} - - - coffee_provider_token: - value: {get_input: coffee_provider_token} - conditions: {logic_expression: has_coffee} - - - payment_provider_endpoint: {get_input: payment_provider_endpoint} - - payment_provider_token: {get_input: payment_provider_token} - - - payment_merchant_a_enabled: - value: true - conditions: {logic_expression: has_payment_merchant_a} - - - payment_merchant_a_enabled: - value: false - conditions: {not: {logic_expression: has_payment_merchant_a}} - - - payment_merchant_b_enabled: - value: true - conditions: {logic_expression: has_payment_merchant_b} - - - payment_merchant_b_enabled: - value: false - conditions: {not: {logic_expression: has_payment_merchant_b}} - - requirements: - - host: local_docker_engine - - host: remote_docker_engine - - host: kubernetes_cluster - artifacts: - - docker_image: - type: docker.image - file: retailer.service.core:vX.Y.Z - - ################################################### - # - # Retailer Jobs - # - ################################################### - - retailer_service_jobs: - type: retailer.service.jobs - properties: - - application_name: retailer-service-core - - application_port: 4000 - - application_protocol: graphql - - logging_level: - value: info - conditions: {logic_expression: has_info_logging} - - - logging_level: - value: info - conditions: {logic_expression: has_debug_logging} - - - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} - - requirements: - - host: local_docker_engine - - host: remote_docker_engine - - host: kubernetes_cluster - artifacts: - - docker_image: - type: docker.image - file: retailer.service.jobs:vX.Y.Z - - ################################################### - # - # Retailer Stores - # - ################################################### - - retailer_service_stores: - type: retailer.service.stores - properties: - - application_name: retailer-service-stores - - application_port: 4000 - - application_protocol: graphql - - logging_level: - value: info - conditions: {logic_expression: has_info_logging} - - - logging_level: - value: info - conditions: {logic_expression: has_debug_logging} - - - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} - - - mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} - - mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} - - mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} - - mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} - - mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} - - mysql_table: 'stores' - - mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} - - - bucket_name: {eval: '.::.requirements::[.name=bucket]::.target::bucket_name'} - - bucket_endpoint: {eval: '.::.requirements::[.name=bucket]::.target::bucket_endpoint'} - - bucket_token: {eval: '.::.requirements::[.name=bucket]::.target::bucket_token'} - - bucket_dialect: {eval: '.::.requirements::[.name=bucket]::.target::bucket_dialect'} - - requirements: - - database: retailer_database_stores - - bucket: retailer_bucket_stores - - host: local_docker_engine - - host: remote_docker_engine - - host: kubernetes_cluster - artifacts: - - docker_image: - type: docker.image - file: retailer.service.stores:vX.Y.Z - - retailer_database_stores: - type: mysql.database - properties: - - database_name: stores - - database_user: stores - - database_password: {get_input: database_password} - requirements: - - host: retailer_dbms - - retailer_bucket_stores: - type: bucket - properties: - - bucket_name: stores - - bucket_dialect: - value: minio - conditions: {node_presence: retailer_minio} - - - bucket_dialect: - value: gcp - conditions: {node_presence: gcp_cloudstorage} - requirements: - - host: retailer_minio - - host: gcp_cloudstorage - - ################################################### - # - # Retailer Products - # - ################################################### - - retailer_service_products: - type: retailer.service.products - properties: - - application_name: retailer-service-products - - application_port: 4000 - - application_protocol: graphql - - logging_level: - value: info - conditions: {logic_expression: has_info_logging} - - - logging_level: - value: info - conditions: {logic_expression: has_debug_logging} - - - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} - - - import_enabled: - value: true - conditions: {logic_expression: has_import} - - - import_enabled: - value: false - conditions: {not: {logic_expression: has_import}} - - - import_schema: - value: a - conditions: {logic_expression: has_import_schema_a} - - - import_schema: - value: b - conditions: {logic_expression: has_import_schema_b} - - - mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} - - mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} - - mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} - - mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} - - mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} - - mysql_table: 'stores' - - mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} - - - bucket_name: {eval: '.::.requirements::[.name=bucket]::.target::bucket_name'} - - bucket_endpoint: {eval: '.::.requirements::[.name=bucket]::.target::bucket_endpoint'} - - bucket_token: {eval: '.::.requirements::[.name=bucket]::.target::bucket_token'} - - bucket_dialect: {eval: '.::.requirements::[.name=bucket]::.target::bucket_dialect'} - - requirements: - - database: retailer_database_products - - bucket: retailer_bucket_products - - host: local_docker_engine - - host: remote_docker_engine - - host: kubernetes_cluster - artifacts: - - docker_image: - type: docker.image - file: retailer.service.products:vX.Y.Z - - retailer_database_products: - type: mysql.database - properties: - - database_name: products - - database_user: products - - database_password: {get_input: database_password} - requirements: - - host: retailer_dbms - - retailer_bucket_products: - type: bucket - properties: - - bucket_name: products - - bucket_dialect: - value: minio - conditions: {node_presence: retailer_minio} - - - bucket_dialect: - value: gcp - conditions: {node_presence: gcp_cloudstorage} - requirements: - - host: retailer_minio - - host: gcp_cloudstorage - - ################################################### - # - # Retailer Stocks - # - ################################################### - - retailer_service_stocks: - type: retailer.service.stocks - properties: - - application_name: retailer-service-stocks - - application_port: 4000 - - application_protocol: graphql - - logging_level: - value: info - conditions: {logic_expression: has_info_logging} - - - logging_level: - value: info - conditions: {logic_expression: has_debug_logging} - - - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} - - - mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} - - mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} - - mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} - - mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} - - mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} - - mysql_table: 'stores' - - mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} - requirements: - - database: retailer_database_stocks - - host: local_docker_engine - - host: remote_docker_engine - - host: kubernetes_cluster - artifacts: - - docker_image: - type: docker.image - file: retailer.service.stocks:vX.Y.Z - - retailer_database_stocks: - type: mysql.database - properties: - - database_name: stocks - - database_user: stocks - - database_password: {get_input: database_password} - requirements: - - host: retailer_dbms - - ################################################### - # - # Retailer Orders - # - ################################################### - - retailer_service_orders: - type: retailer.service.orders - properties: - - application_name: retailer-service-orders - - application_port: 4000 - - application_protocol: graphql - - logging_level: - value: info - conditions: {logic_expression: has_info_logging} - - - logging_level: - value: info - conditions: {logic_expression: has_debug_logging} - - - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} - - - mysql_host: {eval: '.::.requirements::[.name=database]::.target::application_address'} - - mysql_port: {eval: '.::.requirements::[.name=database]::.target::application_port'} - - mysql_database: {eval: '.::.requirements::[.name=database]::.target::database_name'} - - mysql_user: {eval: '.::.requirements::[.name=database]::.target::database_user'} - - mysql_password: {eval: '.::.requirements::[.name=database]::.target::database_password'} - - mysql_table: 'stores' - - mysql_ssl_mode: {eval: '.::.requirements::[.name=database]::.target::.requirements::[.name=host]::.target::dbms_ssl_mode'} - requirements: - - database: retailer_database_orders - - host: local_docker_engine - - host: remote_docker_engine - - host: kubernetes_cluster - artifacts: - - docker_image: - type: docker.image - file: retailer.service.stocks:vX.Y.Z - - retailer_database_orders: - type: mysql.database - properties: - - database_name: orders - - database_user: orders - - database_password: {get_input: database_password} - requirements: - - host: retailer_dbms - - ################################################### - # - # Retailer Global - # - ################################################### - - retailer_service_global: - type: retailer.service.global - properties: - - application_name: retailer-service-global - - application_port: 4000 - - application_protocol: graphql - - logging_level: - value: info - conditions: {logic_expression: has_info_logging} - - - logging_level: - value: info - conditions: {logic_expression: has_debug_logging} - - - retailer_cache_redis_endpoint: {eval: '.::.requirements::[.name=retailer_cache_redis]::.target::application_endpoint'} - - - global_service_gateway_endpoint: {get_input: global_service_gateway_endpoint} - - global_service_gateway_token: {get_input: global_service_gateway_token} - requirements: - - database: retailer_database_orders - - host: local_docker_engine - - host: remote_docker_engine - - host: kubernetes_cluster - artifacts: - - docker_image: - type: docker.image - file: retailer.service.stocks:vX.Y.Z - - ################################################### - # - # Retailer DBMS - # - ################################################### - - retailer_dbms: - type: mysql.dbms - properties: - - dbms_name: unfurl-technology-industry-dbms - - dbms_password: {get_input: dbms_password} - requirements: - - host: local_docker_engine - - host: remote_docker_engine - - host: kubernetes_cluster - - host: gcp_cloudsql - artifacts: - - dbms_image: - type: dbms.image - file: 5.7 - - ################################################### - # - # Retailer Cache - # - ################################################### - - retailer_cache_redis: - type: redis.server - properties: - - cache_name: retailer-cache-redis - - cache_port: 6379 - requirements: - - host: local_docker_engine - - host: remote_docker_engine - - host: gcp_memorystore - - host: - node: kubernetes_cluster - conditions: {logic_expression: is_customer} - artifacts: - - cache_image: - type: cache.image - file: 7.4.0 - - ################################################### - # - # Retailer MinIO - # - ################################################### - - retailer_minio: - type: minio.server - conditions: {not: {logic_expression: is_hyperscaler}} - properties: - - application_name: retailer-minio-server - - application_port: 9000 - - application_protocol: http - requirements: - - host: local_docker_engine - - host: remote_docker_engine - - host: kubernetes_cluster - artifacts: - - docker_image: - type: docker.image - file: minio/minio:RELEASE.2024-08-29T01-40-52Z - - ################################################### - # - # Local Machine - # - ################################################### - - local_docker_engine: - type: docker.engine - requirements: - - host: local_machine - - local_machine: - type: local.machine - conditions: {logic_expression: is_local} - - ################################################### - # - # Virtual Machine - # - ################################################### - - remote_docker_engine: - type: docker.engine - requirements: - - host: virtual_machine - - virtual_machine: - type: virtual.machine - properties: - - machine_name: unfurl-technology-boutique - - ports: ['80', '2375', '9100'] - - flavor: m1.medium - - network: {get_input: os_network} - - ssh_user: {get_input: os_ssh_user} - - ssh_key_name: {get_input: os_ssh_key_name} - - ssh_key_file: {get_input: os_ssh_key_file} - requirements: - - host: openstack_provider - artifacts: - - machine_image: - type: machine.image - file: Ubuntu 22.04 - - openstack_provider: - type: openstack.provider - conditions: {logic_expression: is_development} - properties: - - os_region_name: {get_input: os_region_name} - - os_auth_type: {get_input: os_auth_type} - - os_auth_url: {get_input: os_auth_url} - - os_identity_api_version: {get_input: os_identity_api_version} - - os_interface: {get_input: os_interface} - - os_application_credential_id: {get_input: os_application_credential_id} - - os_application_credential_secret: {get_input: os_application_credential_secret} - - ################################################### - # - # GCP - # - ################################################### - - gcp_memorystore: - type: gcp.memorystore - requirements: - - host: gcp_provider - - gcp_kubernetesengine: - type: gcp.kubernetesengine - requirements: - - host: gcp_provider - - gcp_cloudstorage: - type: gcp.cloudstorage - requirements: - - host: gcp_provider - - gcp_cloudrun: - type: gcp.cloudrun - requirements: - - host: gcp_provider - - gcp_cloudsql: - type: gcp.cloudsql - requirements: - - host: gcp_provider - - gcp_provider: - type: gcp.provider - conditions: {logic_expression: is_hyperscaler} - properties: - - gcp_region: {get_input: gcp_region} - - gcp_service_account_file: {get_input: gcp_service_account_file} - - gcp_project: {get_input: gcp_project} - - ################################################### - # - # Kubernetes - # - ################################################### - - # TODO: credentials are only present at customer else they are dynamic! - kubernetes_cluster: - type: kubernetes.cluster - properties: - - k8s_host: {get_input: k8s_host} - - k8s_ca_cert_file: {get_input: k8s_ca_cert_file} - - k8s_client_cert_file: {get_input: k8s_client_cert_file} - - k8s_client_key_file: {get_input: k8s_client_key_file} - requirements: - - host: kubernetes_provider - - host: gcp_kubernetesengine - - kubernetes_provider: - type: cloud.provider - conditions: {logic_expression: is_customer} From ab3fe906afe9336d3c7d238376f5f60b2af3b301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Sun, 8 Sep 2024 17:57:23 +0200 Subject: [PATCH 16/18] fixes --- .../machine/local-machine/terraform/index.ts | 11 +------ .../plugins/rules/generators/index.ts | 4 +-- .../local-machine/terraform/index.ts | 17 ++-------- .../machine/local-machine/terraform/index.ts | 11 +------ .../machine/local-machine/terraform/index.ts | 2 +- .../machine/local-machine/terraform/index.ts | 9 +---- .../machine/local-machine/terraform/index.ts | 4 --- .../machine/local-machine/ansible/index.ts | 33 +++---------------- .../machine/local-machine/terraform/index.ts | 4 --- 9 files changed, 14 insertions(+), 81 deletions(-) diff --git a/src/technologies/plugins/rules/generators/docker-engine/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/docker-engine/machine/local-machine/terraform/index.ts index f9f0e6fbae..0b8d79296c 100644 --- a/src/technologies/plugins/rules/generators/docker-engine/machine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/docker-engine/machine/local-machine/terraform/index.ts @@ -49,15 +49,6 @@ const generator: ImplementationGenerator = { ...TerraformRequiredVersion(), }, ], - provider: { - local: [ - { - endpoint: `${LOCALHOST}:{{ HOST.management_port }}`, - password: '{{ HOST.dbms_password }}', - username: 'root', - }, - ], - }, resource: { local_file: { tmp_service: { @@ -66,7 +57,7 @@ const generator: ImplementationGenerator = { }, }, terraform_data: { - docker: [ + local: [ { depends_on: 'local_file.tmp_service', provisioner: { diff --git a/src/technologies/plugins/rules/generators/index.ts b/src/technologies/plugins/rules/generators/index.ts index c12e4ff477..d2eb48eb8b 100644 --- a/src/technologies/plugins/rules/generators/index.ts +++ b/src/technologies/plugins/rules/generators/index.ts @@ -7,7 +7,7 @@ import mysqlDBMS from './mysql-dbms' import redisServer from './redis-server' import serviceApplication from './service-application' import softwareApplication from './software-application' -import remoteMachine from './virtual-machine' +import virtualMachine from './virtual-machine' export default [ bucket, @@ -19,5 +19,5 @@ export default [ redisServer, serviceApplication, softwareApplication, - remoteMachine, + virtualMachine, ] diff --git a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/terraform/index.ts index efb7ac23e4..23cb4084fd 100644 --- a/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-database/mysql-dbms/docker-engine/local-machine/terraform/index.ts @@ -1,11 +1,6 @@ import {ImplementationGenerator} from '#technologies/plugins/rules/types' import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' -import { - MetadataGenerated, - MetadataUnfurl, - OpenstackMachineCredentials, - OpenstackMachineHost, -} from '#technologies/plugins/rules/utils/utils' +import {MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' // TODO: we assume that dbms is exposed @@ -13,10 +8,8 @@ const generator: ImplementationGenerator = { component: 'mysql.database', technology: 'terraform', hosting: ['mysql.dbms', 'docker.engine', 'local.machine'], - - // TODO: what is about the weight? SSH workaround not used anymore - weight: 0.5, - reason: 'Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized.', + weight: 1, + reason: 'Terraform provides a declarative module.', generate: (name, type) => { return { @@ -25,10 +18,6 @@ const generator: ImplementationGenerator = { ...MetadataGenerated(), ...MetadataUnfurl(), }, - properties: { - ...OpenstackMachineCredentials(), - ...OpenstackMachineHost(), - }, interfaces: { ...TerraformStandardOperations(), defaults: { diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/local-machine/terraform/index.ts index d3c7fadff5..b44d040e68 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/docker-engine/machine/local-machine/terraform/index.ts @@ -5,12 +5,7 @@ import { TerraformDockerProviderLocalConfiguration, TerraformStandardOperations, } from '#technologies/plugins/rules/utils/terraform' -import { - MetadataGenerated, - MetadataUnfurl, - OpenstackMachineCredentials, - OpenstackMachineHost, -} from '#technologies/plugins/rules/utils/utils' +import {MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' const generator: ImplementationGenerator = { component: 'mysql.dbms', @@ -28,10 +23,6 @@ const generator: ImplementationGenerator = { ...MetadataGenerated(), ...MetadataUnfurl(), }, - properties: { - ...OpenstackMachineCredentials(), - ...OpenstackMachineHost(), - }, attributes: { application_address: { type: 'string', diff --git a/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/terraform/index.ts index 932d6d3539..f73fbbb814 100644 --- a/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/mysql-dbms/dbms-image/machine/local-machine/terraform/index.ts @@ -15,7 +15,7 @@ const generator: ImplementationGenerator = { weight: 0, reason: 'Ansible is more specialized. Also using provisioners is a "last resort".', details: - '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner', + '"local_file" resource to create the installation script and "terraform_data" to execute the script using the "local-exec" provisioner', generate: (name, type) => { return { diff --git a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/terraform/index.ts index 3ecbd8053b..fc964b7843 100644 --- a/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/apt-package/asterisk/machine/local-machine/terraform/index.ts @@ -9,12 +9,7 @@ import { } from '#technologies/plugins/rules/generators/software-application/utils' import {GeneratorAbstract} from '#technologies/plugins/rules/types' import {TerraformStandardOperations} from '#technologies/plugins/rules/utils/terraform' -import { - ApplicationDirectory, - MetadataGenerated, - OpenstackMachineCredentials, - OpenstackMachineHost, -} from '#technologies/plugins/rules/utils/utils' +import {ApplicationDirectory, MetadataGenerated} from '#technologies/plugins/rules/utils/utils' import * as utils from '#utils' class Generator extends GeneratorAbstract { @@ -31,8 +26,6 @@ class Generator extends GeneratorAbstract { derived_from: name, metadata: {...MetadataGenerated()}, properties: { - ...OpenstackMachineCredentials(), - ...OpenstackMachineHost(), ...ApplicationDirectory(), }, interfaces: { diff --git a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts index 798b9f1860..0f3281bb29 100644 --- a/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/tar-archive/asterisk/machine/local-machine/terraform/index.ts @@ -12,8 +12,6 @@ import { ApplicationDirectory, JinjaWhenSourceArchiveFile, MetadataGenerated, - OpenstackMachineCredentials, - OpenstackMachineHost, SourceArchiveFile, } from '#technologies/plugins/rules/utils/utils' @@ -31,8 +29,6 @@ class Generator extends GeneratorAbstract { derived_from: name, metadata: {...MetadataGenerated()}, properties: { - ...OpenstackMachineCredentials(), - ...OpenstackMachineHost(), ...ApplicationDirectory(), }, interfaces: { diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts index ff0736e807..56b3425a46 100644 --- a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/ansible/index.ts @@ -7,7 +7,7 @@ import { AnsibleSoftwareApplicationStopTasks, } from '#technologies/plugins/rules/generators/software-application/utils' import {GeneratorAbstract} from '#technologies/plugins/rules/types' -import {AnsibleOrchestratorOperation, AnsibleWaitForSSHTask} from '#technologies/plugins/rules/utils/ansible' +import {AnsibleOrchestratorOperation} from '#technologies/plugins/rules/utils/ansible' import {ApplicationDirectory, MetadataGenerated, MetadataUnfurl} from '#technologies/plugins/rules/utils/utils' class Generator extends GeneratorAbstract { @@ -41,9 +41,6 @@ class Generator extends GeneratorAbstract { inputs: { playbook: { q: [ - { - ...AnsibleWaitForSSHTask(), - }, { name: 'install operational dependencies', 'ansible.builtin.apt': { @@ -65,12 +62,7 @@ class Generator extends GeneratorAbstract { }, inputs: { playbook: { - q: [ - { - ...AnsibleWaitForSSHTask(), - }, - ...AnsibleSoftwareApplicationConfigureTasks(), - ], + q: [...AnsibleSoftwareApplicationConfigureTasks()], }, }, }, @@ -80,12 +72,7 @@ class Generator extends GeneratorAbstract { }, inputs: { playbook: { - q: [ - { - ...AnsibleWaitForSSHTask(), - }, - ...AnsibleSoftwareApplicationStartTasks(), - ], + q: [...AnsibleSoftwareApplicationStartTasks()], }, }, }, @@ -95,12 +82,7 @@ class Generator extends GeneratorAbstract { }, inputs: { playbook: { - q: [ - { - ...AnsibleWaitForSSHTask(), - }, - ...AnsibleSoftwareApplicationStopTasks(), - ], + q: [...AnsibleSoftwareApplicationStopTasks()], }, }, }, @@ -110,12 +92,7 @@ class Generator extends GeneratorAbstract { }, inputs: { playbook: { - q: [ - { - ...AnsibleWaitForSSHTask(), - }, - ...AnsibleSoftwareApplicationDeleteTasks(), - ], + q: [...AnsibleSoftwareApplicationDeleteTasks()], }, }, }, diff --git a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts index 616a382ecc..3f2c6fcaf9 100644 --- a/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/software-application/zip-archive/asterisk/machine/local-machine/terraform/index.ts @@ -12,8 +12,6 @@ import { ApplicationDirectory, JinjaWhenSourceArchiveFile, MetadataGenerated, - OpenstackMachineCredentials, - OpenstackMachineHost, SourceArchiveFile, } from '#technologies/plugins/rules/utils/utils' @@ -31,8 +29,6 @@ class Generator extends GeneratorAbstract { derived_from: name, metadata: {...MetadataGenerated()}, properties: { - ...OpenstackMachineCredentials(), - ...OpenstackMachineHost(), ...ApplicationDirectory(), }, interfaces: { From f98f888b9484ba0bda54c5ab36d29a8ba488d259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Sun, 8 Sep 2024 18:01:15 +0200 Subject: [PATCH 17/18] minor --- .../bucket/gcp-cloudstorage/ansible/index.ts | 4 ++-- .../minio/asterisk/local-machine/ansible/index.ts | 1 - .../minio/asterisk/remote-machine/ansible/index.ts | 1 - .../bucket/minio/kubernetes-cluster/ansible/index.ts | 1 - .../cache-image/gcp-memorystore/ansible/index.ts | 4 ++-- .../cache-image/kubernetes-cluster/ansible/index.ts | 4 ++-- .../cache-image/kubernetes-cluster/terraform/index.ts | 10 +++------- 7 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts b/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts index 1a46ee957e..2bb6a8c808 100644 --- a/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/bucket/gcp-cloudstorage/ansible/index.ts @@ -8,8 +8,8 @@ const generator: ImplementationGenerator = { component: 'bucket', technology: 'ansible', hosting: ['gcp.cloudstorage'], - weight: 0.5, - reason: 'Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this.', + weight: 1, + reason: 'Primary use case due to the specialization of Ansible.', generate: (name, type) => { return { diff --git a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/ansible/index.ts index 31e2bc62d6..1255b9b820 100644 --- a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/local-machine/ansible/index.ts @@ -8,7 +8,6 @@ const generator: ImplementationGenerator = { component: 'bucket', technology: 'ansible', hosting: ['minio.server', '*', 'local.machine'], - // TODO: which weight? most likely 1 weight: 1, reason: 'Primary use case due to the specialization of Ansible.', diff --git a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/ansible/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/ansible/index.ts index f1086537f0..75fe24f13d 100644 --- a/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/bucket/minio/asterisk/remote-machine/ansible/index.ts @@ -8,7 +8,6 @@ const generator: ImplementationGenerator = { component: 'bucket', technology: 'ansible', hosting: ['minio.server', '*', 'remote.machine'], - // TODO: which weight? most likely 1 weight: 1, reason: 'Primary use case due to the specialization of Ansible.', diff --git a/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/ansible/index.ts b/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/ansible/index.ts index 4f0976e980..1003f6d0b1 100644 --- a/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/bucket/minio/kubernetes-cluster/ansible/index.ts @@ -8,7 +8,6 @@ const generator: ImplementationGenerator = { component: 'bucket', technology: 'ansible', hosting: ['minio.server', 'kubernetes.cluster'], - // TODO: which weight? most likely 1 weight: 1, reason: 'Primary use case due to the specialization of Ansible.', diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/ansible/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/ansible/index.ts index fb06c98094..9d2e345857 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/gcp-memorystore/ansible/index.ts @@ -9,8 +9,8 @@ const generator: ImplementationGenerator = { technology: 'ansible', artifact: 'cache.image', hosting: ['gcp.memorystore'], - weight: 0.5, - reason: 'Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this.', + weight: 1, + reason: 'Primary use case due to the specialization of Ansible.', generate: (name, type) => { return { diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts index f3bfb01f2f..199f8a1e15 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/ansible/index.ts @@ -9,8 +9,8 @@ const generator: ImplementationGenerator = { technology: 'ansible', artifact: 'cache.image', hosting: ['kubernetes.cluster'], - weight: 1, - reason: 'Primary use case due to the specialization of Ansible.', + weight: 0.5, + reason: 'Kubernetes is more specialized.', generate: (name, type) => { return { diff --git a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts index 9fe03d4a46..d913721369 100644 --- a/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts +++ b/src/technologies/plugins/rules/generators/redis-server/cache-image/kubernetes-cluster/terraform/index.ts @@ -9,8 +9,8 @@ const generator: ImplementationGenerator = { technology: 'terraform', artifact: 'cache.image', hosting: ['kubernetes.cluster'], - weight: 1, - reason: 'Terraform provides a declarative module.', + weight: 0.5, + reason: 'Kubernetes is more specialized.', generate: (name, type) => { return { @@ -24,11 +24,7 @@ const generator: ImplementationGenerator = { }, interfaces: { - ...TerraformStandardOperations({ - GOOGLE_APPLICATION_CREDENTIALS: { - eval: '.::gcp_service_account_file', - }, - }), + ...TerraformStandardOperations(), defaults: { inputs: { main: { From ded5cf480c7be2b92a4e7017d26df6eb2f31d20f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Sun, 8 Sep 2024 18:04:46 +0200 Subject: [PATCH 18/18] 2nd tipp --- docs/docs/variability4tosca/rules/index.md | 49 ++++++++++--------- .../rules/technology-rules.yaml | 22 ++++----- tasks/docs/generate/rules/template.ejs | 5 +- 3 files changed, 41 insertions(+), 35 deletions(-) diff --git a/docs/docs/variability4tosca/rules/index.md b/docs/docs/variability4tosca/rules/index.md index 3163a8570b..cdd40f9746 100644 --- a/docs/docs/variability4tosca/rules/index.md +++ b/docs/docs/variability4tosca/rules/index.md @@ -9,8 +9,11 @@ tags: # Deployment Technology Rules Specification 1.0 Release Candidate -!!! info - Quick Tip: Elements in graphs can be clicked to open their type definition! +!!! info "Quick Tip #1" + Elements in graphs can be clicked to open their type definition! + +!!! info "Quick Tip #2" + You can query technology rules for your deployment scenario using `vintner utils scenarios`! {{ autogenerated_notice('./task docs:generate:rules') }} @@ -73,8 +76,8 @@ The node template is hosted on the node template "host 1" of node type [gcp.clou
component(bucket)host 1(gcp.cloudstorage)host
-!!! info "Ansible (Quality: 0.5)" - Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. !!! success "Terraform (Quality: 1)" Terraform provides a declarative module. @@ -90,8 +93,8 @@ The node template is hosted on the node template "host 1" of node type [gcp.memo
component(bucket)artifact(cache.image)host 1(gcp.memorystore)host
-!!! info "Ansible (Quality: 0.5)" - Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. +!!! success "Ansible (Quality: 1)" + Primary use case due to the specialization of Ansible. @@ -276,8 +279,8 @@ The node template is hosted on the node template "host 1" of node type [mysql.db !!! failure "Docker Compose (Quality: 0)" One-time use docker container ("fake Kubernetes job") with imperative parts, while other technologies provide declarative modules. -!!! info "Terraform (Quality: 0.5)" - Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. +!!! success "Terraform (Quality: 1)" + Terraform provides a declarative module. @@ -551,11 +554,11 @@ The node template is hosted on the node template "host 1" of node type [kubernet
component(redis.server)artifact(cache.image)host 1(kubernetes.cluster)host
-!!! success "Ansible (Quality: 1)" - Primary use case due to the specialization of Ansible. +!!! info "Ansible (Quality: 0.5)" + Kubernetes is more specialized. -!!! success "Terraform (Quality: 1)" - Terraform provides a declarative module. +!!! info "Terraform (Quality: 0.5)" + Kubernetes is more specialized. @@ -878,8 +881,8 @@ This appendix contains the deployment technology rules. | Component | [bucket](/normative#bucket){target=_blank} | | Technology | ansible | | Hosting | [gcp.cloudstorage](/normative#gcpcloudstorage){target=_blank} | -| Quality | 0.5 | -| Reason | Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | | Details | | | Graph |
component(bucket)host 1(gcp.cloudstorage)host
| @@ -903,8 +906,8 @@ This appendix contains the deployment technology rules. | Artifact | [cache.image](/normative#cacheimage){target=_blank} | | Technology | ansible | | Hosting | [gcp.memorystore](/normative#gcpmemorystore){target=_blank} | -| Quality | 0.5 | -| Reason | Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. | +| Quality | 1 | +| Reason | Primary use case due to the specialization of Ansible. | | Details | | | Graph |
component(bucket)artifact(cache.image)host 1(gcp.memorystore)host
| @@ -1165,8 +1168,8 @@ This appendix contains the deployment technology rules. | Component | [mysql.database](/normative#mysqldatabase){target=_blank} | | Technology | terraform | | Hosting | [mysql.dbms](/normative#mysqldbms){target=_blank} -> [docker.engine](/normative#dockerengine){target=_blank} -> [local.machine](/normative#localmachine){target=_blank} | -| Quality | 0.5 | -| Reason | Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. | +| Quality | 1 | +| Reason | Terraform provides a declarative module. | | Details | | | Graph |
component(mysql.database)host 1(mysql.dbms)host 2(docker.engine)host 3(local.machine)hosthosthost
| @@ -1480,7 +1483,7 @@ This appendix contains the deployment technology rules. | Hosting | [local.machine](/normative#localmachine){target=_blank} | | Quality | 0 | | Reason | Ansible is more specialized. Also using provisioners is a "last resort". | -| Details | "terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner | +| Details | "local_file" resource to create the installation script and "terraform_data" to execute the script using the "local-exec" provisioner | | Graph |
component(mysql.dbms)artifact(dbms.image)host 1(local.machine)host
| ### Rule #51 @@ -1608,8 +1611,8 @@ This appendix contains the deployment technology rules. | Artifact | [cache.image](/normative#cacheimage){target=_blank} | | Technology | ansible | | Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | -| Quality | 1 | -| Reason | Primary use case due to the specialization of Ansible. | +| Quality | 0.5 | +| Reason | Kubernetes is more specialized. | | Details | | | Graph |
component(redis.server)artifact(cache.image)host 1(kubernetes.cluster)host
| @@ -1621,8 +1624,8 @@ This appendix contains the deployment technology rules. | Artifact | [cache.image](/normative#cacheimage){target=_blank} | | Technology | terraform | | Hosting | [kubernetes.cluster](/normative#kubernetescluster){target=_blank} | -| Quality | 1 | -| Reason | Terraform provides a declarative module. | +| Quality | 0.5 | +| Reason | Kubernetes is more specialized. | | Details | | | Graph |
component(redis.server)artifact(cache.image)host 1(kubernetes.cluster)host
| diff --git a/docs/docs/variability4tosca/rules/technology-rules.yaml b/docs/docs/variability4tosca/rules/technology-rules.yaml index cfd78be74a..f1d65b452e 100644 --- a/docs/docs/variability4tosca/rules/technology-rules.yaml +++ b/docs/docs/variability4tosca/rules/technology-rules.yaml @@ -2,8 +2,8 @@ component: bucket hosting: - gcp.cloudstorage - weight: 0.5 - reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. + weight: 1 + reason: Primary use case due to the specialization of Ansible. - technology: terraform component: bucket hosting: @@ -15,8 +15,8 @@ artifact: cache.image hosting: - gcp.memorystore - weight: 0.5 - reason: Primary use case due to the specialization of Ansible. However, need to install and handle GCP CloudSQL Proxy, while the corresponding Terraform module already provides this. + weight: 1 + reason: Primary use case due to the specialization of Ansible. - technology: ansible component: bucket hosting: @@ -174,8 +174,8 @@ - mysql.dbms - docker.engine - local.machine - weight: 0.5 - reason: Terraform provides a declarative module. However, Terraform requires an SSH workaround. Ansible is more specialized. + weight: 1 + reason: Terraform provides a declarative module. - technology: ansible component: mysql.database hosting: @@ -372,7 +372,7 @@ - local.machine weight: 0 reason: Ansible is more specialized. Also using provisioners is a "last resort". - details: '"terraform_data" resource with an "ssh" connection to the virtual machine to copy the install script using the "file" provisioner on the virtual machine and to execute the script using the "remote-exec" provisioner' + details: '"local_file" resource to create the installation script and "terraform_data" to execute the script using the "local-exec" provisioner' - technology: ansible component: mysql.dbms artifact: dbms.image @@ -455,15 +455,15 @@ artifact: cache.image hosting: - kubernetes.cluster - weight: 1 - reason: Primary use case due to the specialization of Ansible. + weight: 0.5 + reason: Kubernetes is more specialized. - technology: terraform component: redis.server artifact: cache.image hosting: - kubernetes.cluster - weight: 1 - reason: Terraform provides a declarative module. + weight: 0.5 + reason: Kubernetes is more specialized. - technology: ansible component: service.application artifact: docker.image diff --git a/tasks/docs/generate/rules/template.ejs b/tasks/docs/generate/rules/template.ejs index a01d29a242..bbd7cd89d2 100644 --- a/tasks/docs/generate/rules/template.ejs +++ b/tasks/docs/generate/rules/template.ejs @@ -9,9 +9,12 @@ tags: # Deployment Technology Rules Specification 1.0 Release Candidate -!!! info "Quick Tip" +!!! info "Quick Tip #1" Elements in graphs can be clicked to open their type definition! +!!! info "Quick Tip #2" + You can query technology rules for your deployment scenario using `vintner utils scenarios`! + {{ autogenerated_notice('./task docs:generate:rules') }} This document specifies the deployment technology rules.