From afdaf11339a30baef762207e3c55e73df934d2a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miles=20St=C3=B6tzner?= Date: Wed, 6 Mar 2024 12:51:40 +0100 Subject: [PATCH] unfurl technology example --- .github/actions/vintner-test/action.yaml | 14 + .../case-study-unfurl-technology.yaml | 222 +++++ cmds/pull-examples.sh | 14 +- docs/cmds/sofdcar/generate.ts | 4 +- docs/cmds/variability/generate.ts | 3 +- docs/docs/assets/documents/dependencies.csv | 408 ++++----- docs/docs/contributing/notes.md | 6 +- docs/docs/contributing/setup.md | 1 + docs/docs/dependencies.md | 390 ++++----- docs/docs/interface.md | 4 +- docs/docs/orchestrators.md | 15 + .../variability4tosca/specification/index.md | 32 +- .../variability4tosca/tests/introduction.md | 4 +- .../test-technologies-ambiguous-disabled.md | 2 +- .../tests/test-technologies-conditional.md | 2 +- .../tests/test-technologies-default-true.md | 2 +- .../tests/test-technologies-lowercase.md | 2 +- .../test-technologies-optimization-double.md | 4 +- .../test-technologies-optimization-order.md | 4 +- .../test-technologies-optimization-weight.md | 4 +- .../tests/test-technologies-optimization.md | 4 +- .../tests/test-technologies-rules.md | 6 +- .../test-technologies-unique-disabled.md | 2 +- docs/overrides/overrides/features.html | 2 +- examples/unfurl-artifacts/scripts/reimport.sh | 2 +- .../.gitignore | 2 + .../config.yaml | 3 + .../stats.sh | 4 + .../tests/elastic/expected.yaml | 53 ++ .../tests/elastic/test.yaml | 1 + .../tests/static-large/expected.yaml | 90 ++ .../tests/static-large/test.yaml | 1 + .../tests/static/expected.yaml | 90 ++ .../tests/static/test.yaml | 1 + .../variable-service-template.yaml | 194 +++++ .../.gitignore | 2 + .../config.yaml | 3 + .../stats.sh | 4 + .../tests/elastic/expected.yaml | 53 ++ .../tests/elastic/test.yaml | 1 + .../tests/static-large/expected.yaml | 90 ++ .../tests/static-large/test.yaml | 1 + .../tests/static/expected.yaml | 90 ++ .../tests/static/test.yaml | 1 + .../variable-service-template.yaml | 191 ++++ .../files/mysql.dbms.create.sh | 37 + .../files/shop.create.sh | 72 ++ .../files/shop.docker.tar.gz | 3 + .../files/shop.source.tar.gz | 3 + .../files/shop.source.zip | 3 + .../lib-loc.sh | 4 + .../lib/gcp.app_engine.yaml | 144 +++ .../lib/gcp.cloud_sql.yaml | 246 ++++++ .../lib/kubernetes.yaml | 20 + .../lib/mysql.database.yaml | 287 ++++++ .../lib/mysql.dbms.yaml | 459 ++++++++++ .../lib/os.compute.yaml | 271 ++++++ .../lib/rules.yaml | 88 ++ .../lib/shop.component.yaml | 820 ++++++++++++++++++ .../lib/types.yaml | 16 + .../scripts/clean.sh | 7 + .../scripts/code.sh | 7 + .../scripts/configuration.env | 4 + .../scripts/configuration.sh | 29 + .../scripts/continue.sh | 7 + .../scripts/deploy.sh | 11 + .../scripts/quality.sh | 8 + .../scripts/reimport.sh | 15 + .../scripts/setup.sh | 10 + .../scripts/undeploy.sh | 7 + .../stats.sh | 4 + .../tests/elastic/test.yaml | 2 + .../tests/static-large/test.yaml | 2 + .../tests/static/test.yaml | 2 + .../variable-service-template.yaml | 194 +++++ .../.gitignore | 2 + .../config.yaml | 3 + .../scripts/clean.sh | 7 + .../scripts/code.sh | 7 + .../scripts/configuration.env | 4 + .../scripts/configuration.sh | 29 + .../scripts/continue.sh | 7 + .../scripts/deploy.sh | 11 + .../scripts/quality.sh | 8 + .../scripts/reimport.sh | 15 + .../scripts/setup.sh | 10 + .../scripts/undeploy.sh | 7 + .../stats.sh | 4 + .../variable-service-template.yaml | 53 ++ .../.gitignore | 2 + .../config.yaml | 3 + .../scripts/configuration.env | 3 + .../scripts/configuration.sh | 23 + .../scripts/quality.sh | 8 + .../stats.sh | 4 + .../variable-service-template.yaml | 73 ++ .../.gitignore | 2 + .../config.yaml | 3 + .../scripts/configuration.env | 3 + .../scripts/configuration.sh | 23 + .../scripts/quality.sh | 8 + .../stats.sh | 4 + .../variable-service-template.yaml | 90 ++ .../.gitignore | 2 + .../config.yaml | 3 + .../scripts/configuration.env | 3 + .../scripts/configuration.sh | 23 + .../scripts/quality.sh | 8 + .../stats.sh | 4 + .../variable-service-template.yaml | 90 ++ .../unfurl-technology-maintenance/.gitignore | 2 + .../unfurl-technology-maintenance/config.yaml | 3 + .../unfurl-technology-maintenance/stats.sh | 4 + .../tests/elastic/test.yaml | 2 + .../tests/kubernetes/test.yaml | 2 + .../tests/static-large/test.yaml | 2 + .../tests/static/test.yaml | 2 + .../variable-service-template.yaml | 252 ++++++ examples/unfurl-technology-manual/.gitignore | 2 + examples/unfurl-technology-manual/config.yaml | 3 + examples/unfurl-technology-manual/stats.sh | 4 + .../tests/elastic/test.yaml | 2 + .../tests/static-large/test.yaml | 2 + .../tests/static/test.yaml | 2 + .../variable-service-template.yaml | 207 +++++ package.json | 2 + patches/lnk+1.1.0.patch | 9 + src/assets/scripts/install-unfurl.sh | 3 +- src/assets/scripts/install-xopera.sh | 2 +- .../templates/template-init/scripts/pull.sh | 0 .../template-init/scripts/quality.sh | 8 + src/cli/program.ts | 4 +- src/controller/instances/adapt.ts | 2 +- src/controller/instances/resolve.ts | 2 +- src/controller/instances/validate.ts | 6 +- src/controller/setup/benchmark.ts | 2 +- src/controller/template/normalize.ts | 4 +- src/controller/template/pull.ts | 19 +- src/controller/template/puml/topology.ts | 4 +- src/controller/template/puml/types.ts | 4 +- src/controller/template/query.ts | 3 +- src/controller/template/stats.ts | 69 +- src/controller/template/test.ts | 8 +- src/enricher/elements.ts | 5 +- src/graph/graph.ts | 17 +- src/graph/loader.ts | 23 +- src/graph/plugin.ts | 38 +- src/graph/technology.ts | 2 + src/normalizer/index.ts | 1 + src/orchestrators/index.ts | 2 +- src/orchestrators/xopera.ts | 10 +- src/query/plugins/file.ts | 5 +- src/query/plugins/winery.ts | 6 +- src/repositories/instances.ts | 11 +- src/repositories/templates.ts | 4 +- src/resolver/index.ts | 5 +- src/resolver/optimizer.ts | 17 +- src/resolver/result.ts | 21 +- src/resolver/transformer.ts | 19 +- src/specification/technology-template.ts | 4 + src/utils/files.ts | 52 +- tests/benchmark/test.ts | 5 +- .../ambiguous-disabled/expected.yaml | 2 +- .../technologies/conditional/expected.yaml | 2 +- .../technologies/default-true/expected.yaml | 2 +- .../technologies/lowercase/expected.yaml | 2 +- .../optimization-double/expected.yaml | 4 +- .../optimization-order/expected.yaml | 4 +- .../optimization-weight/expected.yaml | 4 +- .../technologies/optimization/expected.yaml | 4 +- .../technologies/rules/expected.yaml | 6 +- .../unique-disabled/expected.yaml | 2 +- .../plugins/technology/terraform/index.js | 6 +- .../plugin/index.js | 6 +- tests/integration/adaptation.test.ts | 11 +- tests/integration/swap.test.ts | 15 +- tests/utils.ts | 4 +- yarn.lock | 24 +- 178 files changed, 5723 insertions(+), 623 deletions(-) create mode 100644 .github/workflows/case-study-unfurl-technology.yaml create mode 100644 examples/unfurl-technology-automated-counting/.gitignore create mode 100644 examples/unfurl-technology-automated-counting/config.yaml create mode 100644 examples/unfurl-technology-automated-counting/stats.sh create mode 100644 examples/unfurl-technology-automated-counting/tests/elastic/expected.yaml create mode 100644 examples/unfurl-technology-automated-counting/tests/elastic/test.yaml create mode 100644 examples/unfurl-technology-automated-counting/tests/static-large/expected.yaml create mode 100644 examples/unfurl-technology-automated-counting/tests/static-large/test.yaml create mode 100644 examples/unfurl-technology-automated-counting/tests/static/expected.yaml create mode 100644 examples/unfurl-technology-automated-counting/tests/static/test.yaml create mode 100644 examples/unfurl-technology-automated-counting/variable-service-template.yaml create mode 100644 examples/unfurl-technology-automated-random/.gitignore create mode 100644 examples/unfurl-technology-automated-random/config.yaml create mode 100644 examples/unfurl-technology-automated-random/stats.sh create mode 100644 examples/unfurl-technology-automated-random/tests/elastic/expected.yaml create mode 100644 examples/unfurl-technology-automated-random/tests/elastic/test.yaml create mode 100644 examples/unfurl-technology-automated-random/tests/static-large/expected.yaml create mode 100644 examples/unfurl-technology-automated-random/tests/static-large/test.yaml create mode 100644 examples/unfurl-technology-automated-random/tests/static/expected.yaml create mode 100644 examples/unfurl-technology-automated-random/tests/static/test.yaml create mode 100644 examples/unfurl-technology-automated-random/variable-service-template.yaml create mode 100644 examples/unfurl-technology-automated-weighted/files/mysql.dbms.create.sh create mode 100644 examples/unfurl-technology-automated-weighted/files/shop.create.sh create mode 100644 examples/unfurl-technology-automated-weighted/files/shop.docker.tar.gz create mode 100644 examples/unfurl-technology-automated-weighted/files/shop.source.tar.gz create mode 100644 examples/unfurl-technology-automated-weighted/files/shop.source.zip create mode 100644 examples/unfurl-technology-automated-weighted/lib-loc.sh create mode 100644 examples/unfurl-technology-automated-weighted/lib/gcp.app_engine.yaml create mode 100644 examples/unfurl-technology-automated-weighted/lib/gcp.cloud_sql.yaml create mode 100644 examples/unfurl-technology-automated-weighted/lib/kubernetes.yaml create mode 100644 examples/unfurl-technology-automated-weighted/lib/mysql.database.yaml create mode 100644 examples/unfurl-technology-automated-weighted/lib/mysql.dbms.yaml create mode 100644 examples/unfurl-technology-automated-weighted/lib/os.compute.yaml create mode 100644 examples/unfurl-technology-automated-weighted/lib/rules.yaml create mode 100644 examples/unfurl-technology-automated-weighted/lib/shop.component.yaml create mode 100644 examples/unfurl-technology-automated-weighted/lib/types.yaml create mode 100755 examples/unfurl-technology-automated-weighted/scripts/clean.sh create mode 100755 examples/unfurl-technology-automated-weighted/scripts/code.sh create mode 100644 examples/unfurl-technology-automated-weighted/scripts/configuration.env create mode 100755 examples/unfurl-technology-automated-weighted/scripts/configuration.sh create mode 100755 examples/unfurl-technology-automated-weighted/scripts/continue.sh create mode 100755 examples/unfurl-technology-automated-weighted/scripts/deploy.sh create mode 100644 examples/unfurl-technology-automated-weighted/scripts/quality.sh create mode 100755 examples/unfurl-technology-automated-weighted/scripts/reimport.sh create mode 100755 examples/unfurl-technology-automated-weighted/scripts/setup.sh create mode 100755 examples/unfurl-technology-automated-weighted/scripts/undeploy.sh create mode 100644 examples/unfurl-technology-automated-weighted/stats.sh create mode 100644 examples/unfurl-technology-automated-weighted/tests/elastic/test.yaml create mode 100644 examples/unfurl-technology-automated-weighted/tests/static-large/test.yaml create mode 100644 examples/unfurl-technology-automated-weighted/tests/static/test.yaml create mode 100644 examples/unfurl-technology-automated-weighted/variable-service-template.yaml create mode 100644 examples/unfurl-technology-baseline-elastic/.gitignore create mode 100644 examples/unfurl-technology-baseline-elastic/config.yaml create mode 100644 examples/unfurl-technology-baseline-elastic/scripts/clean.sh create mode 100644 examples/unfurl-technology-baseline-elastic/scripts/code.sh create mode 100644 examples/unfurl-technology-baseline-elastic/scripts/configuration.env create mode 100644 examples/unfurl-technology-baseline-elastic/scripts/configuration.sh create mode 100644 examples/unfurl-technology-baseline-elastic/scripts/continue.sh create mode 100644 examples/unfurl-technology-baseline-elastic/scripts/deploy.sh create mode 100644 examples/unfurl-technology-baseline-elastic/scripts/quality.sh create mode 100644 examples/unfurl-technology-baseline-elastic/scripts/reimport.sh create mode 100644 examples/unfurl-technology-baseline-elastic/scripts/setup.sh create mode 100644 examples/unfurl-technology-baseline-elastic/scripts/undeploy.sh create mode 100644 examples/unfurl-technology-baseline-elastic/stats.sh create mode 100644 examples/unfurl-technology-baseline-elastic/variable-service-template.yaml create mode 100644 examples/unfurl-technology-baseline-kubernetes/.gitignore create mode 100644 examples/unfurl-technology-baseline-kubernetes/config.yaml create mode 100644 examples/unfurl-technology-baseline-kubernetes/scripts/configuration.env create mode 100644 examples/unfurl-technology-baseline-kubernetes/scripts/configuration.sh create mode 100644 examples/unfurl-technology-baseline-kubernetes/scripts/quality.sh create mode 100644 examples/unfurl-technology-baseline-kubernetes/stats.sh create mode 100644 examples/unfurl-technology-baseline-kubernetes/variable-service-template.yaml create mode 100644 examples/unfurl-technology-baseline-static-large/.gitignore create mode 100644 examples/unfurl-technology-baseline-static-large/config.yaml create mode 100644 examples/unfurl-technology-baseline-static-large/scripts/configuration.env create mode 100644 examples/unfurl-technology-baseline-static-large/scripts/configuration.sh create mode 100644 examples/unfurl-technology-baseline-static-large/scripts/quality.sh create mode 100644 examples/unfurl-technology-baseline-static-large/stats.sh create mode 100644 examples/unfurl-technology-baseline-static-large/variable-service-template.yaml create mode 100644 examples/unfurl-technology-baseline-static/.gitignore create mode 100644 examples/unfurl-technology-baseline-static/config.yaml create mode 100644 examples/unfurl-technology-baseline-static/scripts/configuration.env create mode 100644 examples/unfurl-technology-baseline-static/scripts/configuration.sh create mode 100644 examples/unfurl-technology-baseline-static/scripts/quality.sh create mode 100644 examples/unfurl-technology-baseline-static/stats.sh create mode 100644 examples/unfurl-technology-baseline-static/variable-service-template.yaml create mode 100644 examples/unfurl-technology-maintenance/.gitignore create mode 100644 examples/unfurl-technology-maintenance/config.yaml create mode 100644 examples/unfurl-technology-maintenance/stats.sh create mode 100644 examples/unfurl-technology-maintenance/tests/elastic/test.yaml create mode 100644 examples/unfurl-technology-maintenance/tests/kubernetes/test.yaml create mode 100644 examples/unfurl-technology-maintenance/tests/static-large/test.yaml create mode 100644 examples/unfurl-technology-maintenance/tests/static/test.yaml create mode 100644 examples/unfurl-technology-maintenance/variable-service-template.yaml create mode 100644 examples/unfurl-technology-manual/.gitignore create mode 100644 examples/unfurl-technology-manual/config.yaml create mode 100644 examples/unfurl-technology-manual/stats.sh create mode 100644 examples/unfurl-technology-manual/tests/elastic/test.yaml create mode 100644 examples/unfurl-technology-manual/tests/static-large/test.yaml create mode 100644 examples/unfurl-technology-manual/tests/static/test.yaml create mode 100644 examples/unfurl-technology-manual/variable-service-template.yaml create mode 100644 patches/lnk+1.1.0.patch mode change 100644 => 100755 src/assets/templates/template-init/scripts/pull.sh create mode 100755 src/assets/templates/template-init/scripts/quality.sh diff --git a/.github/actions/vintner-test/action.yaml b/.github/actions/vintner-test/action.yaml index aa6fe48610..8a7b1c6580 100644 --- a/.github/actions/vintner-test/action.yaml +++ b/.github/actions/vintner-test/action.yaml @@ -13,6 +13,7 @@ inputs: options: - OS - GCP + - K8S runs: using: 'composite' @@ -40,3 +41,16 @@ runs: run: curl --fail-with-body https://${EXAMPLE}-dot-stoetzms-387808.ey.r.appspot.com env: EXAMPLE: ${{ inputs.example }} + + - name: (VINTNER) Test application + if: ${{ inputs.env == 'K8S' }} + shell: bash + run: | + MINIKUBE_IP=$(minikube ip) + + echo "minikube ip: ${MINIKUBE_IP}" + + curl --fail-with-body https://${MINIKUBE_IP}:${PORT} + env: + EXAMPLE: ${{ inputs.example }} + PORT: ${{ inputs.port }} diff --git a/.github/workflows/case-study-unfurl-technology.yaml b/.github/workflows/case-study-unfurl-technology.yaml new file mode 100644 index 0000000000..d66af9d5d7 --- /dev/null +++ b/.github/workflows/case-study-unfurl-technology.yaml @@ -0,0 +1,222 @@ +name: Case Study "Unfurl Technology" +on: + workflow_dispatch: + +jobs: + ################################################### + # + # Kubernetes + # + ################################################### + + kubernetes: + name: Kubernetes + runs-on: ubuntu-22.04 + env: + ORCHESTRATOR: unfurl + EXAMPLE: unfurl-technology-maintenance + PRESET: kubernetes + ENV: K8S + PORT: 30080 + steps: + ################################################### + # + # Prepare + # + ################################################### + + - name: (PREPARE) Checkout repository + uses: actions/checkout@v3 + with: + lfs: true + + - name: (PREPARE) Start minikube + uses: medyagh/setup-minikube@v0.0.15 + + - name: (PREPARE) Install Vintner + uses: ./.github/actions/vintner-install + with: + gcp_service_account_file: ${{ secrets.GCP_SERVICE_ACCOUNT_FILE }} + os_ssh_key_file: ${{ secrets.OS_SSH_KEY_FILE }} + os_application_credential_id: ${{ secrets.OS_APPLICATION_CREDENTIAL_ID }} + os_application_credential_secret: ${{ secrets.OS_APPLICATION_CREDENTIAL_SECRET }} + + - name: (VINTNER) Configure setup + uses: ./.github/actions/vintner-setup + with: + orchestrator: ${{ env.ORCHESTRATOR }} + + - name: (VINTNER) Resolve variability + uses: ./.github/actions/vintner-resolve + with: + example: ${{ env.EXAMPLE }} + preset: ${{ env.PRESET }} + + - name: (VINTNER) Assign deployment inputs + run: | + cat << EOF > /tmp/deployment-inputs.yaml + k8s_api_port: $(minikube ip) + k8s_ca_cert_file: /home/runner/.minikube/ca.crt + k8s_client_cert_file: /home/runner/.minikube/profiles/minikube/client.crt + k8s_client_key_file: /home/runner/.minikube/profiles/minikube/client.key + EOF + + - name: (VINTNER) Validate application + uses: ./.github/actions/vintner-validate + + - name: (VINTNER) Deploy application + uses: ./.github/actions/vintner-deploy + + - name: (VINTNER) Test application + uses: ./.github/actions/vintner-test + with: + example: ${{ env.EXAMPLE }} + env: ${{ env.ENV }} + port: ${{ env.PORT }} + + - name: (VINTNER) Undeploy application + uses: ./.github/actions/vintner-undeploy + if: always() + + ################################################### + # + # GCP + # + ################################################### + + gcp: + name: GCP + runs-on: ubuntu-22.04 + env: + ORCHESTRATOR: unfurl + EXAMPLE: unfurl-technology-maintenance + PRESET: elastic + ENV: GCP + PORT: 80 + steps: + ################################################### + # + # Prepare + # + ################################################### + + - name: (PREPARE) Checkout repository + uses: actions/checkout@v3 + with: + lfs: true + + - name: (PREPARE) Install Vintner + uses: ./.github/actions/vintner-install + with: + gcp_service_account_file: ${{ secrets.GCP_SERVICE_ACCOUNT_FILE }} + os_ssh_key_file: ${{ secrets.OS_SSH_KEY_FILE }} + os_application_credential_id: ${{ secrets.OS_APPLICATION_CREDENTIAL_ID }} + os_application_credential_secret: ${{ secrets.OS_APPLICATION_CREDENTIAL_SECRET }} + + - name: (VINTNER) Configure setup + uses: ./.github/actions/vintner-setup + with: + orchestrator: ${{ env.ORCHESTRATOR }} + + - name: (VINTNER) Resolve variability + uses: ./.github/actions/vintner-resolve + with: + example: ${{ env.EXAMPLE }} + preset: ${{ env.PRESET }} + + - name: (VINTNER) Assign deployment inputs + run: | + cat << EOF > /tmp/deployment-inputs.yaml + gcp_service_account_file: /tmp/gcp-service-account-file.json + EOF + + - name: (VINTNER) Validate application + uses: ./.github/actions/vintner-validate + + - name: (VINTNER) Deploy application + uses: ./.github/actions/vintner-deploy + + - name: (VINTNER) Test application + uses: ./.github/actions/vintner-test + with: + example: ${{ env.EXAMPLE }} + env: ${{ env.ENV }} + port: ${{ env.PORT }} + + - name: (VINTNER) Undeploy application + uses: ./.github/actions/vintner-undeploy + if: always() + + ################################################### + # + # OpenStack + # + ################################################### + + openstack: + name: OpenStack + runs-on: ubuntu-22.04 + env: + ORCHESTRATOR: unfurl + EXAMPLE: unfurl-technology-maintenance + PRESET: static + ENV: OS + PORT: 80 + steps: + ################################################### + # + # Prepare + # + ################################################### + + - name: (PREPARE) Checkout repository + uses: actions/checkout@v3 + with: + lfs: true + + - name: (PREPARE) Install Vintner + uses: ./.github/actions/vintner-install + with: + gcp_service_account_file: ${{ secrets.GCP_SERVICE_ACCOUNT_FILE }} + os_ssh_key_file: ${{ secrets.OS_SSH_KEY_FILE }} + os_application_credential_id: ${{ secrets.OS_APPLICATION_CREDENTIAL_ID }} + os_application_credential_secret: ${{ secrets.OS_APPLICATION_CREDENTIAL_SECRET }} + + - name: (VINTNER) Configure setup + uses: ./.github/actions/vintner-setup + with: + orchestrator: ${{ env.ORCHESTRATOR }} + + - name: (VINTNER) Resolve variability + uses: ./.github/actions/vintner-resolve + with: + example: ${{ env.EXAMPLE }} + preset: ${{ env.PRESET }} + + - name: (VINTNER) Assign deployment inputs + run: | + cat << EOF > /tmp/deployment-inputs.yaml + os_application_credential_id: ${OS_APPLICATION_CREDENTIAL_ID} + os_application_credential_secret: ${OS_APPLICATION_CREDENTIAL_SECRET} + os_ssh_key_file: /tmp/os-ssh-key-file + EOF + env: + OS_APPLICATION_CREDENTIAL_ID: ${{ secrets.OS_APPLICATION_CREDENTIAL_ID }} + OS_APPLICATION_CREDENTIAL_SECRET: ${{ secrets.OS_APPLICATION_CREDENTIAL_SECRET }} + + - name: (VINTNER) Validate application + uses: ./.github/actions/vintner-validate + + - name: (VINTNER) Deploy application + uses: ./.github/actions/vintner-deploy + + - name: (VINTNER) Test application + uses: ./.github/actions/vintner-test + with: + example: ${{ env.EXAMPLE }} + env: ${{ env.ENV }} + port: ${{ env.PORT }} + + - name: (VINTNER) Undeploy application + uses: ./.github/actions/vintner-undeploy + if: always() diff --git a/cmds/pull-examples.sh b/cmds/pull-examples.sh index 365aa049ce..09266e8d1b 100755 --- a/cmds/pull-examples.sh +++ b/cmds/pull-examples.sh @@ -14,21 +14,23 @@ if [ ! -f "${ENTRYPOINT}" ]; then exit 1 fi +# Symbolic +LINK=${1:-false} # Pull dependencies of each example -for e in examples/*/; do +for example in examples/*/; do # Ignore directories starting with a dot - if [[ "${e}" == "\."* ]]; then + if [[ "${example}" == "\."* ]]; then continue fi # Ignore directories without config.yaml - if [ ! -f "${e}/config.yaml" ]; then + if [ ! -f "${example}/config.yaml" ]; then continue fi - # Pull dependencies - echo "Pulling ${e}" - $VINTNER template pull --template "${e}" + # Pull dependenciess + echo "Pulling ${example}" + $VINTNER template pull --template "$(realpath ${example})" --link ${LINK} done diff --git a/docs/cmds/sofdcar/generate.ts b/docs/cmds/sofdcar/generate.ts index 9ac5ae38fa..c0ce3cf84f 100644 --- a/docs/cmds/sofdcar/generate.ts +++ b/docs/cmds/sofdcar/generate.ts @@ -1,11 +1,11 @@ import * as files from '#files' -import {ServiceTemplate} from '#spec/service-template' +import Loader from '#graph/loader' import * as utils from '#utils' import * as path from 'path' async function run(name: string, id: string, variant: string) { const dir = path.join('docs', 'docs', 'sofdcar') - const template = files.loadYAML(path.join(dir, name + '.yaml')) + const template = new Loader(path.join(dir, name + '.yaml')).raw() await files.renderFile( path.join(__dirname, 'profile.template.ejs'), { diff --git a/docs/cmds/variability/generate.ts b/docs/cmds/variability/generate.ts index a079288da2..98300a70a0 100644 --- a/docs/cmds/variability/generate.ts +++ b/docs/cmds/variability/generate.ts @@ -7,6 +7,7 @@ import { VariabilityTestConfig, } from '#controller/template/test' import * as files from '#files' +import Loader from '#graph/loader' import {ServiceTemplate} from '#spec/service-template' import {InputAssignmentMap} from '#spec/topology-template' import * as path from 'path' @@ -35,7 +36,7 @@ async function main() { const dir = path.join(groupDir, test) const id = `${group}-${test}` const config = loadConfig(dir) - const template = files.loadYAML(getVariableServiceTemplate({dir, file: config.template})) + const template = new Loader(getVariableServiceTemplate({dir, file: config.template})).raw() const inputs = getDefaultInputs(dir) ? files.loadYAML(getDefaultInputs(dir)!) : undefined diff --git a/docs/docs/assets/documents/dependencies.csv b/docs/docs/assets/documents/dependencies.csv index ad32c49380..b4dc33d44d 100644 --- a/docs/docs/assets/documents/dependencies.csv +++ b/docs/docs/assets/documents/dependencies.csv @@ -1,203 +1,207 @@ -name,version,license,url -@ewoudenberg/difflib,0.1.0,PSF,https://github.com/ewoudenberg/difflib.js -@yarnpkg/lockfile,1.1.0,BSD-2-Clause,https://github.com/yarnpkg/yarn/blob/master/packages/lockfile -accepts,1.3.8,MIT,https://github.com/jshttp/accepts -ansi-styles,4.3.0,MIT,https://github.com/chalk/ansi-styles -anymatch,3.1.3,ISC,https://github.com/micromatch/anymatch -archiver,5.3.1,MIT,https://github.com/archiverjs/node-archiver -archiver-utils,2.1.0,MIT,https://github.com/archiverjs/archiver-utils -argparse,2.0.1,Python-2.0,https://github.com/nodeca/argparse -array-flatten,1.1.1,MIT,https://github.com/blakeembrey/array-flatten -async,3.2.4,MIT,https://github.com/caolan/async -async-mutex,0.4.0,MIT,https://github.com/DirtyHairy/async-mutex -asynckit,0.4.0,MIT,https://github.com/alexindigo/asynckit -at-least-node,1.0.0,ISC,https://github.com/RyanZim/at-least-node -axios,0.27.2,MIT,https://github.com/axios/axios -balanced-match,1.0.2,MIT,https://github.com/juliangruber/balanced-match -base64-js,1.5.1,MIT,https://github.com/beatgammit/base64-js -binary-extensions,2.2.0,MIT,https://github.com/sindresorhus/binary-extensions -bl,4.1.0,MIT,https://github.com/rvagg/bl -body-parser,1.20.1,MIT,https://github.com/expressjs/body-parser -brace-expansion,2.0.1,MIT,https://github.com/juliangruber/brace-expansion -braces,3.0.2,MIT,https://github.com/micromatch/braces -buffer,5.7.1,MIT,https://github.com/feross/buffer -buffer-crc32,0.2.13,MIT,https://github.com/brianloveswords/buffer-crc32 -bytes,3.1.2,MIT,https://github.com/visionmedia/bytes.js -call-bind,1.0.2,MIT,https://github.com/ljharb/call-bind -call-me-maybe,1.0.2,MIT,https://github.com/limulus/call-me-maybe -chalk,4.1.2,MIT,https://github.com/chalk/chalk -chokidar,3.5.3,MIT,https://github.com/paulmillr/chokidar -ci-info,3.8.0,MIT,https://github.com/watson/ci-info -color-convert,2.0.1,MIT,https://github.com/Qix-/color-convert -color-name,1.1.4,MIT,https://github.com/colorjs/color-name -colors,1.4.0,MIT,https://github.com/Marak/colors.js -combined-stream,1.0.8,MIT,https://github.com/felixge/node-combined-stream -commander,10.0.1,MIT,https://github.com/tj/commander.js -compress-commons,4.1.1,MIT,https://github.com/archiverjs/node-compress-commons -concat-map,0.0.1,MIT,https://github.com/substack/node-concat-map -content-disposition,0.5.4,MIT,https://github.com/jshttp/content-disposition -content-type,1.0.5,MIT,https://github.com/jshttp/content-type -cookie,0.5.0,MIT,https://github.com/jshttp/cookie -cookie-signature,1.0.6,MIT,https://github.com/visionmedia/node-cookie-signature -core-util-is,1.0.3,MIT,https://github.com/isaacs/core-util-is -cors,2.8.5,MIT,https://github.com/expressjs/cors -crc-32,1.2.2,Apache-2.0,https://github.com/SheetJS/js-crc32 -crc32-stream,4.0.2,MIT,https://github.com/archiverjs/node-crc32-stream -cross-spawn,7.0.3,MIT,https://github.com/moxystudio/node-cross-spawn -dayjs,1.11.7,MIT,https://github.com/iamkun/dayjs -debug,4.3.4,MIT,https://github.com/debug-js/debug -delayed-stream,1.0.0,MIT,https://github.com/felixge/node-delayed-stream -depd,2.0.0,MIT,https://github.com/dougwilson/nodejs-depd -destroy,1.2.0,MIT,https://github.com/stream-utils/destroy -dreamopt,0.8.0,MIT,https://github.com/andreyvit/dreamopt.js -ee-first,1.1.1,MIT,https://github.com/jonathanong/ee-first -ejs,3.1.9,Apache-2.0,https://github.com/mde/ejs -encodeurl,1.0.2,MIT,https://github.com/pillarjs/encodeurl -end-of-stream,1.4.4,MIT,https://github.com/mafintosh/end-of-stream -es6-promise,4.2.8,MIT,https://github.com/stefanpenner/es6-promise -escape-html,1.0.3,MIT,https://github.com/component/escape-html -etag,1.8.1,MIT,https://github.com/jshttp/etag -express,4.18.2,MIT,https://github.com/expressjs/express -extract-zip,2.0.1,BSD-2-Clause,https://github.com/maxogden/extract-zip -fd-slicer,1.1.0,MIT,https://github.com/andrewrk/node-fd-slicer -filelist,1.0.4,Apache-2.0,https://github.com/mde/filelist -fill-range,7.0.1,MIT,https://github.com/jonschlinkert/fill-range -finalhandler,1.2.0,MIT,https://github.com/pillarjs/finalhandler -find-yarn-workspace-root,2.0.0,Apache-2.0,https://github.com/square/find-yarn-workspace-root -follow-redirects,1.15.2,MIT,https://github.com/follow-redirects/follow-redirects -form-data,4.0.0,MIT,https://github.com/form-data/form-data -forwarded,0.2.0,MIT,https://github.com/jshttp/forwarded -fresh,0.5.2,MIT,https://github.com/jshttp/fresh -friendly-node-cron,1.4.1,MIT,https://github.com/FreaKzero/friendly-node-cron -fs-constants,1.0.0,MIT,https://github.com/mafintosh/fs-constants -fs-extra,11.1.1,MIT,https://github.com/jprichardson/node-fs-extra -fs.realpath,1.0.0,ISC,https://github.com/isaacs/fs.realpath -function-bind,1.1.1,MIT,https://github.com/Raynos/function-bind -get-intrinsic,1.2.0,MIT,https://github.com/ljharb/get-intrinsic -get-stream,5.2.0,MIT,https://github.com/sindresorhus/get-stream -glob,10.1.0,ISC,https://github.com/isaacs/node-glob -glob-parent,5.1.2,ISC,https://github.com/gulpjs/glob-parent -glob-to-regexp,0.3.0,BSD-2-Clause,https://github.com/fitzgen/glob-to-regexp -graceful-fs,4.2.11,ISC,https://github.com/isaacs/node-graceful-fs -has,1.0.3,MIT,https://github.com/tarruda/has -has-flag,4.0.0,MIT,https://github.com/sindresorhus/has-flag -has-symbols,1.0.3,MIT,https://github.com/inspect-js/has-symbols -heap,0.2.7,MIT,https://github.com/qiao/heap.js -http-errors,2.0.0,MIT,https://github.com/jshttp/http-errors -iconv-lite,0.4.24,MIT,https://github.com/ashtuchkin/iconv-lite -ieee754,1.2.1,BSD-3-Clause,https://github.com/feross/ieee754 -inflight,1.0.6,ISC,https://github.com/npm/inflight -inherits,2.0.4,ISC,https://github.com/isaacs/inherits -ipaddr.js,1.9.1,MIT,https://github.com/whitequark/ipaddr.js -is-absolute,1.0.0,MIT,https://github.com/jonschlinkert/is-absolute -is-binary-path,2.1.0,MIT,https://github.com/sindresorhus/is-binary-path -is-docker,2.2.1,MIT,https://github.com/sindresorhus/is-docker -is-extglob,2.1.1,MIT,https://github.com/jonschlinkert/is-extglob -is-glob,4.0.3,MIT,https://github.com/micromatch/is-glob -is-number,7.0.0,MIT,https://github.com/jonschlinkert/is-number -is-relative,1.0.0,MIT,https://github.com/jonschlinkert/is-relative -is-unc-path,1.0.0,MIT,https://github.com/jonschlinkert/is-unc-path -is-windows,1.0.2,MIT,https://github.com/jonschlinkert/is-windows -is-wsl,2.2.0,MIT,https://github.com/sindresorhus/is-wsl -isarray,1.0.0,MIT,https://github.com/juliangruber/isarray -isexe,2.0.0,ISC,https://github.com/isaacs/isexe -isnumber,1.0.0,MIT,https://github.com/brycebaril/node-isnumber -jake,10.8.5,Apache-2.0,https://github.com/jakejs/jake -js-yaml,4.1.0,MIT,https://github.com/nodeca/js-yaml -json-diff,1.0.3,MIT,https://github.com/andreyvit/json-diff -json-stable-stringify,1.0.2,MIT,https://github.com/ljharb/json-stable-stringify -jsonfile,6.1.0,MIT,https://github.com/jprichardson/node-jsonfile -jsonify,0.0.1,Public Domain,https://github.com/ljharb/jsonify -klaw-sync,6.0.0,MIT,https://github.com/manidlou/node-klaw-sync -lazystream,1.0.1,MIT,https://github.com/jpommerening/node-lazystream -lodash,4.17.21,MIT,https://github.com/lodash/lodash -lodash.defaults,4.2.0,MIT,https://github.com/lodash/lodash -lodash.difference,4.5.0,MIT,https://github.com/lodash/lodash -lodash.flatten,4.4.0,MIT,https://github.com/lodash/lodash -lodash.isplainobject,4.0.6,MIT,https://github.com/lodash/lodash -lodash.union,4.6.0,MIT,https://github.com/lodash/lodash -logic-solver,2.0.1,MIT,https://github.com/meteor/logic-solver -lru-cache,9.0.3,ISC,https://github.com/isaacs/node-lru-cache -media-typer,0.3.0,MIT,https://github.com/jshttp/media-typer -merge-descriptors,1.0.1,MIT,https://github.com/component/merge-descriptors -methods,1.1.2,MIT,https://github.com/jshttp/methods -micromatch,4.0.5,MIT,https://github.com/micromatch/micromatch -mime,1.6.0,MIT,https://github.com/broofa/node-mime -mime-db,1.52.0,MIT,https://github.com/jshttp/mime-db -mime-types,2.1.35,MIT,https://github.com/jshttp/mime-types -minimatch,9.0.0,ISC,https://github.com/isaacs/minimatch -minimist,1.2.8,MIT,https://github.com/minimistjs/minimist -minipass,5.0.0,ISC,https://github.com/isaacs/minipass -ms,2.1.3,MIT,https://github.com/vercel/ms -negotiator,0.6.3,MIT,https://github.com/jshttp/negotiator -node-cron,3.0.2,ISC,https://github.com/merencia/node-cron -normalize-path,3.0.0,MIT,https://github.com/jonschlinkert/normalize-path -object-assign,4.1.1,MIT,https://github.com/sindresorhus/object-assign -object-inspect,1.12.3,MIT,https://github.com/inspect-js/object-inspect -ohm-js,16.4.0,MIT,https://github.com/harc/ohm -on-finished,2.4.1,MIT,https://github.com/jshttp/on-finished -once,1.4.0,ISC,https://github.com/isaacs/once -open,7.4.2,MIT,https://github.com/sindresorhus/open -opentosca-vintner,0.1.4,Apache-2.0,https://github.com/OpenTOSCA/opentosca-vintner -os-tmpdir,1.0.2,MIT,https://github.com/sindresorhus/os-tmpdir -papaparse,5.4.1,MIT,https://github.com/mholt/PapaParse -parseurl,1.3.3,MIT,https://github.com/pillarjs/parseurl -patch-package,8.0.0,MIT,https://github.com/ds300/patch-package -path-is-absolute,1.0.1,MIT,https://github.com/sindresorhus/path-is-absolute -path-key,3.1.1,MIT,https://github.com/sindresorhus/path-key -path-scurry,1.7.0,BlueOak-1.0.0,https://github.com/isaacs/path-walker -path-to-regexp,0.1.7,MIT,https://github.com/component/path-to-regexp -pend,1.2.0,MIT,https://github.com/andrewrk/node-pend -picomatch,2.3.1,MIT,https://github.com/micromatch/picomatch -process-nextick-args,2.0.1,MIT,https://github.com/calvinmetcalf/process-nextick-args -proxy-addr,2.0.7,MIT,https://github.com/jshttp/proxy-addr -pump,3.0.0,MIT,https://github.com/mafintosh/pump -qs,6.11.0,BSD-3-Clause,https://github.com/ljharb/qs -range-parser,1.2.1,MIT,https://github.com/jshttp/range-parser -raw-body,2.5.1,MIT,https://github.com/stream-utils/raw-body -readable-stream,3.6.2,MIT,https://github.com/nodejs/readable-stream -readdir-enhanced,1.5.2,MIT,https://github.com/bigstickcarpet/readdir-enhanced -readdir-glob,1.1.3,Apache-2.0,https://github.com/Yqnn/node-readdir-glob -readdirp,3.6.0,MIT,https://github.com/paulmillr/readdirp -regression,2.0.1,MIT,https://github.com/Tom-Alexander/regression-js -rimraf,2.7.1,ISC,https://github.com/isaacs/rimraf -safe-buffer,5.2.1,MIT,https://github.com/feross/safe-buffer -safer-buffer,2.1.2,MIT,https://github.com/ChALkeR/safer-buffer -sax,1.2.4,ISC,https://github.com/isaacs/sax-js -semver,7.5.4,ISC,https://github.com/npm/node-semver -send,0.18.0,MIT,https://github.com/pillarjs/send -serve-static,1.15.0,MIT,https://github.com/expressjs/serve-static -setprototypeof,1.2.0,ISC,https://github.com/wesleytodd/setprototypeof -shebang-command,2.0.0,MIT,https://github.com/kevva/shebang-command -shebang-regex,3.0.0,MIT,https://github.com/sindresorhus/shebang-regex -side-channel,1.0.4,MIT,https://github.com/ljharb/side-channel -slash,2.0.0,MIT,https://github.com/sindresorhus/slash -stats-lite,2.2.0,MIT,https://github.com/brycebaril/node-stats-lite -statuses,2.0.1,MIT,https://github.com/jshttp/statuses -string_decoder,1.3.0,MIT,https://github.com/nodejs/string_decoder -supports-color,7.2.0,MIT,https://github.com/chalk/supports-color -sync-directory,6.0.4,ISC,https://github.com/hoperyy/sync-directory -systeminformation,5.21.8,MIT,https://github.com/sebhildebrandt/systeminformation -tar-stream,2.2.0,MIT,https://github.com/mafintosh/tar-stream -tmp,0.0.33,MIT,https://github.com/raszi/node-tmp -to-regex-range,5.0.1,MIT,https://github.com/micromatch/to-regex-range -toidentifier,1.0.1,MIT,https://github.com/component/toidentifier -tslib,2.5.0,0BSD,https://github.com/Microsoft/tslib -type-is,1.6.18,MIT,https://github.com/jshttp/type-is -unc-path-regex,0.1.2,MIT,https://github.com/regexhq/unc-path-regex -underscore,1.13.6,MIT,https://github.com/jashkenas/underscore -universalify,2.0.0,MIT,https://github.com/RyanZim/universalify -unpipe,1.0.0,MIT,https://github.com/stream-utils/unpipe -util-deprecate,1.0.2,MIT,https://github.com/TooTallNate/util-deprecate -utils-merge,1.0.1,MIT,https://github.com/jaredhanson/utils-merge -uuid,9.0.0,MIT,https://github.com/uuidjs/uuid -vary,1.1.2,MIT,https://github.com/jshttp/vary -which,2.0.2,ISC,https://github.com/isaacs/node-which -wordwrap,1.0.0,MIT,https://github.com/substack/node-wordwrap -wrappy,1.0.2,ISC,https://github.com/npm/wrappy -xml2js,0.5.0,MIT,https://github.com/Leonidas-from-XIV/node-xml2js -xmlbuilder,11.0.1,MIT,https://github.com/oozcitak/xmlbuilder-js -yallist,4.0.0,ISC,https://github.com/isaacs/yallist -yaml,2.3.2,ISC,https://github.com/eemeli/yaml -yauzl,2.10.0,MIT,https://github.com/thejoshwolfe/yauzl +name,version,license,url +@ewoudenberg/difflib,0.1.0,PSF,https://github.com/ewoudenberg/difflib.js +@yarnpkg/lockfile,1.1.0,BSD-2-Clause,https://github.com/yarnpkg/yarn/blob/master/packages/lockfile +accepts,1.3.8,MIT,https://github.com/jshttp/accepts +ansi-styles,4.3.0,MIT,https://github.com/chalk/ansi-styles +anymatch,3.1.3,ISC,https://github.com/micromatch/anymatch +archiver,5.3.1,MIT,https://github.com/archiverjs/node-archiver +archiver-utils,2.1.0,MIT,https://github.com/archiverjs/archiver-utils +argparse,2.0.1,Python-2.0,https://github.com/nodeca/argparse +array-flatten,1.1.1,MIT,https://github.com/blakeembrey/array-flatten +arrify,1.0.1,MIT,https://github.com/sindresorhus/arrify +async,3.2.4,MIT,https://github.com/caolan/async +async-mutex,0.4.0,MIT,https://github.com/DirtyHairy/async-mutex +asynckit,0.4.0,MIT,https://github.com/alexindigo/asynckit +at-least-node,1.0.0,ISC,https://github.com/RyanZim/at-least-node +axios,0.27.2,MIT,https://github.com/axios/axios +balanced-match,1.0.2,MIT,https://github.com/juliangruber/balanced-match +base64-js,1.5.1,MIT,https://github.com/beatgammit/base64-js +binary-extensions,2.2.0,MIT,https://github.com/sindresorhus/binary-extensions +bl,4.1.0,MIT,https://github.com/rvagg/bl +body-parser,1.20.1,MIT,https://github.com/expressjs/body-parser +brace-expansion,2.0.1,MIT,https://github.com/juliangruber/brace-expansion +braces,3.0.2,MIT,https://github.com/micromatch/braces +buffer,5.7.1,MIT,https://github.com/feross/buffer +buffer-crc32,0.2.13,MIT,https://github.com/brianloveswords/buffer-crc32 +bytes,3.1.2,MIT,https://github.com/visionmedia/bytes.js +call-bind,1.0.2,MIT,https://github.com/ljharb/call-bind +call-me-maybe,1.0.2,MIT,https://github.com/limulus/call-me-maybe +chalk,4.1.2,MIT,https://github.com/chalk/chalk +chokidar,3.5.3,MIT,https://github.com/paulmillr/chokidar +ci-info,3.8.0,MIT,https://github.com/watson/ci-info +color-convert,2.0.1,MIT,https://github.com/Qix-/color-convert +color-name,1.1.4,MIT,https://github.com/colorjs/color-name +colors,1.4.0,MIT,https://github.com/Marak/colors.js +combined-stream,1.0.8,MIT,https://github.com/felixge/node-combined-stream +commander,10.0.1,MIT,https://github.com/tj/commander.js +compress-commons,4.1.1,MIT,https://github.com/archiverjs/node-compress-commons +concat-map,0.0.1,MIT,https://github.com/substack/node-concat-map +content-disposition,0.5.4,MIT,https://github.com/jshttp/content-disposition +content-type,1.0.5,MIT,https://github.com/jshttp/content-type +cookie,0.5.0,MIT,https://github.com/jshttp/cookie +cookie-signature,1.0.6,MIT,https://github.com/visionmedia/node-cookie-signature +core-util-is,1.0.3,MIT,https://github.com/isaacs/core-util-is +cors,2.8.5,MIT,https://github.com/expressjs/cors +crc-32,1.2.2,Apache-2.0,https://github.com/SheetJS/js-crc32 +crc32-stream,4.0.2,MIT,https://github.com/archiverjs/node-crc32-stream +cross-spawn,7.0.3,MIT,https://github.com/moxystudio/node-cross-spawn +dayjs,1.11.7,MIT,https://github.com/iamkun/dayjs +debug,4.3.4,MIT,https://github.com/debug-js/debug +delayed-stream,1.0.0,MIT,https://github.com/felixge/node-delayed-stream +depd,2.0.0,MIT,https://github.com/dougwilson/nodejs-depd +destroy,1.2.0,MIT,https://github.com/stream-utils/destroy +dreamopt,0.8.0,MIT,https://github.com/andreyvit/dreamopt.js +ee-first,1.1.1,MIT,https://github.com/jonathanong/ee-first +ejs,3.1.9,Apache-2.0,https://github.com/mde/ejs +encodeurl,1.0.2,MIT,https://github.com/pillarjs/encodeurl +end-of-stream,1.4.4,MIT,https://github.com/mafintosh/end-of-stream +es6-promise,4.2.8,MIT,https://github.com/stefanpenner/es6-promise +escape-html,1.0.3,MIT,https://github.com/component/escape-html +etag,1.8.1,MIT,https://github.com/jshttp/etag +express,4.18.2,MIT,https://github.com/expressjs/express +extract-zip,2.0.1,BSD-2-Clause,https://github.com/maxogden/extract-zip +fd-slicer,1.1.0,MIT,https://github.com/andrewrk/node-fd-slicer +filelist,1.0.4,Apache-2.0,https://github.com/mde/filelist +fill-range,7.0.1,MIT,https://github.com/jonschlinkert/fill-range +finalhandler,1.2.0,MIT,https://github.com/pillarjs/finalhandler +find-yarn-workspace-root,2.0.0,Apache-2.0,https://github.com/square/find-yarn-workspace-root +follow-redirects,1.15.2,MIT,https://github.com/follow-redirects/follow-redirects +form-data,4.0.0,MIT,https://github.com/form-data/form-data +forwarded,0.2.0,MIT,https://github.com/jshttp/forwarded +fresh,0.5.2,MIT,https://github.com/jshttp/fresh +friendly-node-cron,1.4.1,MIT,https://github.com/FreaKzero/friendly-node-cron +fs-constants,1.0.0,MIT,https://github.com/mafintosh/fs-constants +fs-extra,11.1.1,MIT,https://github.com/jprichardson/node-fs-extra +fs.realpath,1.0.0,ISC,https://github.com/isaacs/fs.realpath +function-bind,1.1.1,MIT,https://github.com/Raynos/function-bind +get-intrinsic,1.2.0,MIT,https://github.com/ljharb/get-intrinsic +get-stream,5.2.0,MIT,https://github.com/sindresorhus/get-stream +glob,10.1.0,ISC,https://github.com/isaacs/node-glob +glob-parent,5.1.2,ISC,https://github.com/gulpjs/glob-parent +glob-to-regexp,0.3.0,BSD-2-Clause,https://github.com/fitzgen/glob-to-regexp +graceful-fs,4.2.11,ISC,https://github.com/isaacs/node-graceful-fs +has,1.0.3,MIT,https://github.com/tarruda/has +has-flag,4.0.0,MIT,https://github.com/sindresorhus/has-flag +has-symbols,1.0.3,MIT,https://github.com/inspect-js/has-symbols +heap,0.2.7,MIT,https://github.com/qiao/heap.js +http-errors,2.0.0,MIT,https://github.com/jshttp/http-errors +iconv-lite,0.4.24,MIT,https://github.com/ashtuchkin/iconv-lite +ieee754,1.2.1,BSD-3-Clause,https://github.com/feross/ieee754 +inflight,1.0.6,ISC,https://github.com/npm/inflight +inherits,2.0.4,ISC,https://github.com/isaacs/inherits +ipaddr.js,1.9.1,MIT,https://github.com/whitequark/ipaddr.js +is-absolute,1.0.0,MIT,https://github.com/jonschlinkert/is-absolute +is-binary-path,2.1.0,MIT,https://github.com/sindresorhus/is-binary-path +is-docker,2.2.1,MIT,https://github.com/sindresorhus/is-docker +is-extglob,2.1.1,MIT,https://github.com/jonschlinkert/is-extglob +is-glob,4.0.3,MIT,https://github.com/micromatch/is-glob +is-number,7.0.0,MIT,https://github.com/jonschlinkert/is-number +is-relative,1.0.0,MIT,https://github.com/jonschlinkert/is-relative +is-unc-path,1.0.0,MIT,https://github.com/jonschlinkert/is-unc-path +is-windows,1.0.2,MIT,https://github.com/jonschlinkert/is-windows +is-wsl,2.2.0,MIT,https://github.com/sindresorhus/is-wsl +isarray,1.0.0,MIT,https://github.com/juliangruber/isarray +isexe,2.0.0,ISC,https://github.com/isaacs/isexe +isnumber,1.0.0,MIT,https://github.com/brycebaril/node-isnumber +jake,10.8.5,Apache-2.0,https://github.com/jakejs/jake +js-yaml,4.1.0,MIT,https://github.com/nodeca/js-yaml +json-diff,1.0.3,MIT,https://github.com/andreyvit/json-diff +json-stable-stringify,1.0.2,MIT,https://github.com/ljharb/json-stable-stringify +jsonfile,6.1.0,MIT,https://github.com/jprichardson/node-jsonfile +jsonify,0.0.1,Public Domain,https://github.com/ljharb/jsonify +klaw-sync,6.0.0,MIT,https://github.com/manidlou/node-klaw-sync +lazystream,1.0.1,MIT,https://github.com/jpommerening/node-lazystream +lnk,1.1.0,MIT,https://github.com/schnittstabil/lnk +lodash,4.17.21,MIT,https://github.com/lodash/lodash +lodash.defaults,4.2.0,MIT,https://github.com/lodash/lodash +lodash.difference,4.5.0,MIT,https://github.com/lodash/lodash +lodash.flatten,4.4.0,MIT,https://github.com/lodash/lodash +lodash.isplainobject,4.0.6,MIT,https://github.com/lodash/lodash +lodash.union,4.6.0,MIT,https://github.com/lodash/lodash +logic-solver,2.0.1,MIT,https://github.com/meteor/logic-solver +lru-cache,9.0.3,ISC,https://github.com/isaacs/node-lru-cache +media-typer,0.3.0,MIT,https://github.com/jshttp/media-typer +merge-descriptors,1.0.1,MIT,https://github.com/component/merge-descriptors +methods,1.1.2,MIT,https://github.com/jshttp/methods +micromatch,4.0.5,MIT,https://github.com/micromatch/micromatch +mime,1.6.0,MIT,https://github.com/broofa/node-mime +mime-db,1.52.0,MIT,https://github.com/jshttp/mime-db +mime-types,2.1.35,MIT,https://github.com/jshttp/mime-types +minimatch,9.0.0,ISC,https://github.com/isaacs/minimatch +minimist,1.2.8,MIT,https://github.com/minimistjs/minimist +minipass,5.0.0,ISC,https://github.com/isaacs/minipass +mkdirp,0.5.6,MIT,https://github.com/substack/node-mkdirp +ms,2.1.3,MIT,https://github.com/vercel/ms +negotiator,0.6.3,MIT,https://github.com/jshttp/negotiator +node-cron,3.0.2,ISC,https://github.com/merencia/node-cron +normalize-path,3.0.0,MIT,https://github.com/jonschlinkert/normalize-path +object-assign,4.1.1,MIT,https://github.com/sindresorhus/object-assign +object-inspect,1.12.3,MIT,https://github.com/inspect-js/object-inspect +ohm-js,16.4.0,MIT,https://github.com/harc/ohm +on-finished,2.4.1,MIT,https://github.com/jshttp/on-finished +once,1.4.0,ISC,https://github.com/isaacs/once +open,7.4.2,MIT,https://github.com/sindresorhus/open +opentosca-vintner,0.1.4,Apache-2.0,https://github.com/OpenTOSCA/opentosca-vintner +os-tmpdir,1.0.2,MIT,https://github.com/sindresorhus/os-tmpdir +papaparse,5.4.1,MIT,https://github.com/mholt/PapaParse +parseurl,1.3.3,MIT,https://github.com/pillarjs/parseurl +patch-package,8.0.0,MIT,https://github.com/ds300/patch-package +path-is-absolute,1.0.1,MIT,https://github.com/sindresorhus/path-is-absolute +path-key,3.1.1,MIT,https://github.com/sindresorhus/path-key +path-scurry,1.7.0,BlueOak-1.0.0,https://github.com/isaacs/path-walker +path-to-regexp,0.1.7,MIT,https://github.com/component/path-to-regexp +pend,1.2.0,MIT,https://github.com/andrewrk/node-pend +picomatch,2.3.1,MIT,https://github.com/micromatch/picomatch +pify,2.3.0,MIT,https://github.com/sindresorhus/pify +process-nextick-args,2.0.1,MIT,https://github.com/calvinmetcalf/process-nextick-args +proxy-addr,2.0.7,MIT,https://github.com/jshttp/proxy-addr +pump,3.0.0,MIT,https://github.com/mafintosh/pump +qs,6.11.0,BSD-3-Clause,https://github.com/ljharb/qs +range-parser,1.2.1,MIT,https://github.com/jshttp/range-parser +raw-body,2.5.1,MIT,https://github.com/stream-utils/raw-body +readable-stream,3.6.2,MIT,https://github.com/nodejs/readable-stream +readdir-enhanced,1.5.2,MIT,https://github.com/bigstickcarpet/readdir-enhanced +readdir-glob,1.1.3,Apache-2.0,https://github.com/Yqnn/node-readdir-glob +readdirp,3.6.0,MIT,https://github.com/paulmillr/readdirp +regression,2.0.1,MIT,https://github.com/Tom-Alexander/regression-js +rimraf,2.7.1,ISC,https://github.com/isaacs/rimraf +safe-buffer,5.2.1,MIT,https://github.com/feross/safe-buffer +safer-buffer,2.1.2,MIT,https://github.com/ChALkeR/safer-buffer +sax,1.2.4,ISC,https://github.com/isaacs/sax-js +semver,7.5.4,ISC,https://github.com/npm/node-semver +send,0.18.0,MIT,https://github.com/pillarjs/send +serve-static,1.15.0,MIT,https://github.com/expressjs/serve-static +setprototypeof,1.2.0,ISC,https://github.com/wesleytodd/setprototypeof +shebang-command,2.0.0,MIT,https://github.com/kevva/shebang-command +shebang-regex,3.0.0,MIT,https://github.com/sindresorhus/shebang-regex +side-channel,1.0.4,MIT,https://github.com/ljharb/side-channel +slash,2.0.0,MIT,https://github.com/sindresorhus/slash +stats-lite,2.2.0,MIT,https://github.com/brycebaril/node-stats-lite +statuses,2.0.1,MIT,https://github.com/jshttp/statuses +string_decoder,1.3.0,MIT,https://github.com/nodejs/string_decoder +supports-color,7.2.0,MIT,https://github.com/chalk/supports-color +sync-directory,6.0.4,ISC,https://github.com/hoperyy/sync-directory +systeminformation,5.21.8,MIT,https://github.com/sebhildebrandt/systeminformation +tar-stream,2.2.0,MIT,https://github.com/mafintosh/tar-stream +tmp,0.0.33,MIT,https://github.com/raszi/node-tmp +to-regex-range,5.0.1,MIT,https://github.com/micromatch/to-regex-range +toidentifier,1.0.1,MIT,https://github.com/component/toidentifier +tslib,2.5.0,0BSD,https://github.com/Microsoft/tslib +type-is,1.6.18,MIT,https://github.com/jshttp/type-is +unc-path-regex,0.1.2,MIT,https://github.com/regexhq/unc-path-regex +underscore,1.13.6,MIT,https://github.com/jashkenas/underscore +universalify,2.0.0,MIT,https://github.com/RyanZim/universalify +unpipe,1.0.0,MIT,https://github.com/stream-utils/unpipe +util-deprecate,1.0.2,MIT,https://github.com/TooTallNate/util-deprecate +utils-merge,1.0.1,MIT,https://github.com/jaredhanson/utils-merge +uuid,9.0.0,MIT,https://github.com/uuidjs/uuid +vary,1.1.2,MIT,https://github.com/jshttp/vary +which,2.0.2,ISC,https://github.com/isaacs/node-which +wordwrap,1.0.0,MIT,https://github.com/substack/node-wordwrap +wrappy,1.0.2,ISC,https://github.com/npm/wrappy +xml2js,0.5.0,MIT,https://github.com/Leonidas-from-XIV/node-xml2js +xmlbuilder,11.0.1,MIT,https://github.com/oozcitak/xmlbuilder-js +yallist,4.0.0,ISC,https://github.com/isaacs/yallist +yaml,2.3.2,ISC,https://github.com/eemeli/yaml +yauzl,2.10.0,MIT,https://github.com/thejoshwolfe/yauzl zip-stream,4.1.0,MIT,https://github.com/archiverjs/node-zip-stream \ No newline at end of file diff --git a/docs/docs/contributing/notes.md b/docs/docs/contributing/notes.md index c61ad3c5f9..4d1960731f 100644 --- a/docs/docs/contributing/notes.md +++ b/docs/docs/contributing/notes.md @@ -62,7 +62,7 @@ export type Config = { export type Dependencies = TemplateDependency[] export type TemplateDependency = { source: string - target: string + target?: string } ``` @@ -172,6 +172,10 @@ ssh -N -R 2999:192.168.178.46:3001 pi git update-index --chmod=+x ``` +## bwCloud Blocked Ports + +Some ports are blocked when using bwCloud: https://www.bw-cloud.org/de/bwcloud_scope/netzwerk + ## Naming Convention Types should be named according to the following pattern. diff --git a/docs/docs/contributing/setup.md b/docs/docs/contributing/setup.md index 8b3c45bc1e..aebebbb6b5 100644 --- a/docs/docs/contributing/setup.md +++ b/docs/docs/contributing/setup.md @@ -40,6 +40,7 @@ cd opentosca-vintner git lfs install git lfs pull yarn --immutable +yarn examples:pull:link ``` ## Large Files diff --git a/docs/docs/dependencies.md b/docs/docs/dependencies.md index d1297a22fe..30c344f2dd 100644 --- a/docs/docs/dependencies.md +++ b/docs/docs/dependencies.md @@ -22,200 +22,204 @@ We ensure, that only the licenses [0BSD](https://choosealicense.com/licenses/0bs | 7 | [archiver-utils](https://github.com/archiverjs/archiver-utils){target=_blank} | 2.1.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | | 8 | [argparse](https://github.com/nodeca/argparse){target=_blank} | 2.0.1 | [Python-2.0](https://opensource.org/licenses/Python-2.0){target=_blank} | | 9 | [array-flatten](https://github.com/blakeembrey/array-flatten){target=_blank} | 1.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 10 | [async](https://github.com/caolan/async){target=_blank} | 3.2.4 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 11 | [async-mutex](https://github.com/DirtyHairy/async-mutex){target=_blank} | 0.4.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 12 | [asynckit](https://github.com/alexindigo/asynckit){target=_blank} | 0.4.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 13 | [at-least-node](https://github.com/RyanZim/at-least-node){target=_blank} | 1.0.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 14 | [axios](https://github.com/axios/axios){target=_blank} | 0.27.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 15 | [balanced-match](https://github.com/juliangruber/balanced-match){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 16 | [base64-js](https://github.com/beatgammit/base64-js){target=_blank} | 1.5.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 17 | [binary-extensions](https://github.com/sindresorhus/binary-extensions){target=_blank} | 2.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 18 | [bl](https://github.com/rvagg/bl){target=_blank} | 4.1.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 19 | [body-parser](https://github.com/expressjs/body-parser){target=_blank} | 1.20.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 20 | [brace-expansion](https://github.com/juliangruber/brace-expansion){target=_blank} | 2.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 21 | [braces](https://github.com/micromatch/braces){target=_blank} | 3.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 22 | [buffer](https://github.com/feross/buffer){target=_blank} | 5.7.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 23 | [buffer-crc32](https://github.com/brianloveswords/buffer-crc32){target=_blank} | 0.2.13 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 24 | [bytes](https://github.com/visionmedia/bytes.js){target=_blank} | 3.1.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 25 | [call-bind](https://github.com/ljharb/call-bind){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 26 | [call-me-maybe](https://github.com/limulus/call-me-maybe){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 27 | [chalk](https://github.com/chalk/chalk){target=_blank} | 4.1.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 28 | [chokidar](https://github.com/paulmillr/chokidar){target=_blank} | 3.5.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 29 | [ci-info](https://github.com/watson/ci-info){target=_blank} | 3.8.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 30 | [color-convert](https://github.com/Qix-/color-convert){target=_blank} | 2.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 31 | [color-name](https://github.com/colorjs/color-name){target=_blank} | 1.1.4 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 32 | [colors](https://github.com/Marak/colors.js){target=_blank} | 1.4.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 33 | [combined-stream](https://github.com/felixge/node-combined-stream){target=_blank} | 1.0.8 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 34 | [commander](https://github.com/tj/commander.js){target=_blank} | 10.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 35 | [compress-commons](https://github.com/archiverjs/node-compress-commons){target=_blank} | 4.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 36 | [concat-map](https://github.com/substack/node-concat-map){target=_blank} | 0.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 37 | [content-disposition](https://github.com/jshttp/content-disposition){target=_blank} | 0.5.4 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 38 | [content-type](https://github.com/jshttp/content-type){target=_blank} | 1.0.5 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 39 | [cookie](https://github.com/jshttp/cookie){target=_blank} | 0.5.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 40 | [cookie-signature](https://github.com/visionmedia/node-cookie-signature){target=_blank} | 1.0.6 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 41 | [core-util-is](https://github.com/isaacs/core-util-is){target=_blank} | 1.0.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 42 | [cors](https://github.com/expressjs/cors){target=_blank} | 2.8.5 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 43 | [crc-32](https://github.com/SheetJS/js-crc32){target=_blank} | 1.2.2 | [Apache-2.0](https://choosealicense.com/licenses/apache-2.0){target=_blank} | -| 44 | [crc32-stream](https://github.com/archiverjs/node-crc32-stream){target=_blank} | 4.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 45 | [cross-spawn](https://github.com/moxystudio/node-cross-spawn){target=_blank} | 7.0.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 46 | [dayjs](https://github.com/iamkun/dayjs){target=_blank} | 1.11.7 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 47 | [debug](https://github.com/debug-js/debug){target=_blank} | 4.3.4 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 48 | [delayed-stream](https://github.com/felixge/node-delayed-stream){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 49 | [depd](https://github.com/dougwilson/nodejs-depd){target=_blank} | 2.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 50 | [destroy](https://github.com/stream-utils/destroy){target=_blank} | 1.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 51 | [dreamopt](https://github.com/andreyvit/dreamopt.js){target=_blank} | 0.8.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 52 | [ee-first](https://github.com/jonathanong/ee-first){target=_blank} | 1.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 53 | [ejs](https://github.com/mde/ejs){target=_blank} | 3.1.9 | [Apache-2.0](https://choosealicense.com/licenses/apache-2.0){target=_blank} | -| 54 | [encodeurl](https://github.com/pillarjs/encodeurl){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 55 | [end-of-stream](https://github.com/mafintosh/end-of-stream){target=_blank} | 1.4.4 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 56 | [es6-promise](https://github.com/stefanpenner/es6-promise){target=_blank} | 4.2.8 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 57 | [escape-html](https://github.com/component/escape-html){target=_blank} | 1.0.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 58 | [etag](https://github.com/jshttp/etag){target=_blank} | 1.8.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 59 | [express](https://github.com/expressjs/express){target=_blank} | 4.18.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 60 | [extract-zip](https://github.com/maxogden/extract-zip){target=_blank} | 2.0.1 | [BSD-2-Clause](https://choosealicense.com/licenses/bsd-2-clause){target=_blank} | -| 61 | [fd-slicer](https://github.com/andrewrk/node-fd-slicer){target=_blank} | 1.1.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 62 | [filelist](https://github.com/mde/filelist){target=_blank} | 1.0.4 | [Apache-2.0](https://choosealicense.com/licenses/apache-2.0){target=_blank} | -| 63 | [fill-range](https://github.com/jonschlinkert/fill-range){target=_blank} | 7.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 64 | [finalhandler](https://github.com/pillarjs/finalhandler){target=_blank} | 1.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 65 | [find-yarn-workspace-root](https://github.com/square/find-yarn-workspace-root){target=_blank} | 2.0.0 | [Apache-2.0](https://choosealicense.com/licenses/apache-2.0){target=_blank} | -| 66 | [follow-redirects](https://github.com/follow-redirects/follow-redirects){target=_blank} | 1.15.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 67 | [form-data](https://github.com/form-data/form-data){target=_blank} | 4.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 68 | [forwarded](https://github.com/jshttp/forwarded){target=_blank} | 0.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 69 | [fresh](https://github.com/jshttp/fresh){target=_blank} | 0.5.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 70 | [friendly-node-cron](https://github.com/FreaKzero/friendly-node-cron){target=_blank} | 1.4.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 71 | [fs-constants](https://github.com/mafintosh/fs-constants){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 72 | [fs-extra](https://github.com/jprichardson/node-fs-extra){target=_blank} | 11.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 73 | [fs.realpath](https://github.com/isaacs/fs.realpath){target=_blank} | 1.0.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 74 | [function-bind](https://github.com/Raynos/function-bind){target=_blank} | 1.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 75 | [get-intrinsic](https://github.com/ljharb/get-intrinsic){target=_blank} | 1.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 76 | [get-stream](https://github.com/sindresorhus/get-stream){target=_blank} | 5.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 77 | [glob](https://github.com/isaacs/node-glob){target=_blank} | 10.1.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 78 | [glob-parent](https://github.com/gulpjs/glob-parent){target=_blank} | 5.1.2 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 79 | [glob-to-regexp](https://github.com/fitzgen/glob-to-regexp){target=_blank} | 0.3.0 | [BSD-2-Clause](https://choosealicense.com/licenses/bsd-2-clause){target=_blank} | -| 80 | [graceful-fs](https://github.com/isaacs/node-graceful-fs){target=_blank} | 4.2.11 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 81 | [has](https://github.com/tarruda/has){target=_blank} | 1.0.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 82 | [has-flag](https://github.com/sindresorhus/has-flag){target=_blank} | 4.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 83 | [has-symbols](https://github.com/inspect-js/has-symbols){target=_blank} | 1.0.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 84 | [heap](https://github.com/qiao/heap.js){target=_blank} | 0.2.7 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 85 | [http-errors](https://github.com/jshttp/http-errors){target=_blank} | 2.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 86 | [iconv-lite](https://github.com/ashtuchkin/iconv-lite){target=_blank} | 0.4.24 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 87 | [ieee754](https://github.com/feross/ieee754){target=_blank} | 1.2.1 | [BSD-3-Clause](https://choosealicense.com/licenses/bsd-3-clause){target=_blank} | -| 88 | [inflight](https://github.com/npm/inflight){target=_blank} | 1.0.6 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 89 | [inherits](https://github.com/isaacs/inherits){target=_blank} | 2.0.4 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 90 | [ipaddr.js](https://github.com/whitequark/ipaddr.js){target=_blank} | 1.9.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 91 | [is-absolute](https://github.com/jonschlinkert/is-absolute){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 92 | [is-binary-path](https://github.com/sindresorhus/is-binary-path){target=_blank} | 2.1.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 93 | [is-docker](https://github.com/sindresorhus/is-docker){target=_blank} | 2.2.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 94 | [is-extglob](https://github.com/jonschlinkert/is-extglob){target=_blank} | 2.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 95 | [is-glob](https://github.com/micromatch/is-glob){target=_blank} | 4.0.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 96 | [is-number](https://github.com/jonschlinkert/is-number){target=_blank} | 7.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 97 | [is-relative](https://github.com/jonschlinkert/is-relative){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 98 | [is-unc-path](https://github.com/jonschlinkert/is-unc-path){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 99 | [is-windows](https://github.com/jonschlinkert/is-windows){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 100 | [is-wsl](https://github.com/sindresorhus/is-wsl){target=_blank} | 2.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 101 | [isarray](https://github.com/juliangruber/isarray){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 102 | [isexe](https://github.com/isaacs/isexe){target=_blank} | 2.0.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 103 | [isnumber](https://github.com/brycebaril/node-isnumber){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 104 | [jake](https://github.com/jakejs/jake){target=_blank} | 10.8.5 | [Apache-2.0](https://choosealicense.com/licenses/apache-2.0){target=_blank} | -| 105 | [js-yaml](https://github.com/nodeca/js-yaml){target=_blank} | 4.1.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 106 | [json-diff](https://github.com/andreyvit/json-diff){target=_blank} | 1.0.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 107 | [json-stable-stringify](https://github.com/ljharb/json-stable-stringify){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 108 | [jsonfile](https://github.com/jprichardson/node-jsonfile){target=_blank} | 6.1.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 109 | [jsonify](https://github.com/ljharb/jsonify){target=_blank} | 0.0.1 | [Public](){target=_blank} | +| 10 | [arrify](https://github.com/sindresorhus/arrify){target=_blank} | 1.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 11 | [async](https://github.com/caolan/async){target=_blank} | 3.2.4 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 12 | [async-mutex](https://github.com/DirtyHairy/async-mutex){target=_blank} | 0.4.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 13 | [asynckit](https://github.com/alexindigo/asynckit){target=_blank} | 0.4.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 14 | [at-least-node](https://github.com/RyanZim/at-least-node){target=_blank} | 1.0.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 15 | [axios](https://github.com/axios/axios){target=_blank} | 0.27.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 16 | [balanced-match](https://github.com/juliangruber/balanced-match){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 17 | [base64-js](https://github.com/beatgammit/base64-js){target=_blank} | 1.5.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 18 | [binary-extensions](https://github.com/sindresorhus/binary-extensions){target=_blank} | 2.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 19 | [bl](https://github.com/rvagg/bl){target=_blank} | 4.1.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 20 | [body-parser](https://github.com/expressjs/body-parser){target=_blank} | 1.20.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 21 | [brace-expansion](https://github.com/juliangruber/brace-expansion){target=_blank} | 2.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 22 | [braces](https://github.com/micromatch/braces){target=_blank} | 3.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 23 | [buffer](https://github.com/feross/buffer){target=_blank} | 5.7.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 24 | [buffer-crc32](https://github.com/brianloveswords/buffer-crc32){target=_blank} | 0.2.13 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 25 | [bytes](https://github.com/visionmedia/bytes.js){target=_blank} | 3.1.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 26 | [call-bind](https://github.com/ljharb/call-bind){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 27 | [call-me-maybe](https://github.com/limulus/call-me-maybe){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 28 | [chalk](https://github.com/chalk/chalk){target=_blank} | 4.1.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 29 | [chokidar](https://github.com/paulmillr/chokidar){target=_blank} | 3.5.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 30 | [ci-info](https://github.com/watson/ci-info){target=_blank} | 3.8.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 31 | [color-convert](https://github.com/Qix-/color-convert){target=_blank} | 2.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 32 | [color-name](https://github.com/colorjs/color-name){target=_blank} | 1.1.4 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 33 | [colors](https://github.com/Marak/colors.js){target=_blank} | 1.4.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 34 | [combined-stream](https://github.com/felixge/node-combined-stream){target=_blank} | 1.0.8 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 35 | [commander](https://github.com/tj/commander.js){target=_blank} | 10.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 36 | [compress-commons](https://github.com/archiverjs/node-compress-commons){target=_blank} | 4.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 37 | [concat-map](https://github.com/substack/node-concat-map){target=_blank} | 0.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 38 | [content-disposition](https://github.com/jshttp/content-disposition){target=_blank} | 0.5.4 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 39 | [content-type](https://github.com/jshttp/content-type){target=_blank} | 1.0.5 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 40 | [cookie](https://github.com/jshttp/cookie){target=_blank} | 0.5.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 41 | [cookie-signature](https://github.com/visionmedia/node-cookie-signature){target=_blank} | 1.0.6 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 42 | [core-util-is](https://github.com/isaacs/core-util-is){target=_blank} | 1.0.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 43 | [cors](https://github.com/expressjs/cors){target=_blank} | 2.8.5 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 44 | [crc-32](https://github.com/SheetJS/js-crc32){target=_blank} | 1.2.2 | [Apache-2.0](https://choosealicense.com/licenses/apache-2.0){target=_blank} | +| 45 | [crc32-stream](https://github.com/archiverjs/node-crc32-stream){target=_blank} | 4.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 46 | [cross-spawn](https://github.com/moxystudio/node-cross-spawn){target=_blank} | 7.0.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 47 | [dayjs](https://github.com/iamkun/dayjs){target=_blank} | 1.11.7 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 48 | [debug](https://github.com/debug-js/debug){target=_blank} | 4.3.4 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 49 | [delayed-stream](https://github.com/felixge/node-delayed-stream){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 50 | [depd](https://github.com/dougwilson/nodejs-depd){target=_blank} | 2.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 51 | [destroy](https://github.com/stream-utils/destroy){target=_blank} | 1.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 52 | [dreamopt](https://github.com/andreyvit/dreamopt.js){target=_blank} | 0.8.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 53 | [ee-first](https://github.com/jonathanong/ee-first){target=_blank} | 1.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 54 | [ejs](https://github.com/mde/ejs){target=_blank} | 3.1.9 | [Apache-2.0](https://choosealicense.com/licenses/apache-2.0){target=_blank} | +| 55 | [encodeurl](https://github.com/pillarjs/encodeurl){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 56 | [end-of-stream](https://github.com/mafintosh/end-of-stream){target=_blank} | 1.4.4 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 57 | [es6-promise](https://github.com/stefanpenner/es6-promise){target=_blank} | 4.2.8 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 58 | [escape-html](https://github.com/component/escape-html){target=_blank} | 1.0.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 59 | [etag](https://github.com/jshttp/etag){target=_blank} | 1.8.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 60 | [express](https://github.com/expressjs/express){target=_blank} | 4.18.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 61 | [extract-zip](https://github.com/maxogden/extract-zip){target=_blank} | 2.0.1 | [BSD-2-Clause](https://choosealicense.com/licenses/bsd-2-clause){target=_blank} | +| 62 | [fd-slicer](https://github.com/andrewrk/node-fd-slicer){target=_blank} | 1.1.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 63 | [filelist](https://github.com/mde/filelist){target=_blank} | 1.0.4 | [Apache-2.0](https://choosealicense.com/licenses/apache-2.0){target=_blank} | +| 64 | [fill-range](https://github.com/jonschlinkert/fill-range){target=_blank} | 7.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 65 | [finalhandler](https://github.com/pillarjs/finalhandler){target=_blank} | 1.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 66 | [find-yarn-workspace-root](https://github.com/square/find-yarn-workspace-root){target=_blank} | 2.0.0 | [Apache-2.0](https://choosealicense.com/licenses/apache-2.0){target=_blank} | +| 67 | [follow-redirects](https://github.com/follow-redirects/follow-redirects){target=_blank} | 1.15.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 68 | [form-data](https://github.com/form-data/form-data){target=_blank} | 4.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 69 | [forwarded](https://github.com/jshttp/forwarded){target=_blank} | 0.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 70 | [fresh](https://github.com/jshttp/fresh){target=_blank} | 0.5.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 71 | [friendly-node-cron](https://github.com/FreaKzero/friendly-node-cron){target=_blank} | 1.4.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 72 | [fs-constants](https://github.com/mafintosh/fs-constants){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 73 | [fs-extra](https://github.com/jprichardson/node-fs-extra){target=_blank} | 11.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 74 | [fs.realpath](https://github.com/isaacs/fs.realpath){target=_blank} | 1.0.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 75 | [function-bind](https://github.com/Raynos/function-bind){target=_blank} | 1.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 76 | [get-intrinsic](https://github.com/ljharb/get-intrinsic){target=_blank} | 1.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 77 | [get-stream](https://github.com/sindresorhus/get-stream){target=_blank} | 5.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 78 | [glob](https://github.com/isaacs/node-glob){target=_blank} | 10.1.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 79 | [glob-parent](https://github.com/gulpjs/glob-parent){target=_blank} | 5.1.2 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 80 | [glob-to-regexp](https://github.com/fitzgen/glob-to-regexp){target=_blank} | 0.3.0 | [BSD-2-Clause](https://choosealicense.com/licenses/bsd-2-clause){target=_blank} | +| 81 | [graceful-fs](https://github.com/isaacs/node-graceful-fs){target=_blank} | 4.2.11 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 82 | [has](https://github.com/tarruda/has){target=_blank} | 1.0.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 83 | [has-flag](https://github.com/sindresorhus/has-flag){target=_blank} | 4.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 84 | [has-symbols](https://github.com/inspect-js/has-symbols){target=_blank} | 1.0.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 85 | [heap](https://github.com/qiao/heap.js){target=_blank} | 0.2.7 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 86 | [http-errors](https://github.com/jshttp/http-errors){target=_blank} | 2.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 87 | [iconv-lite](https://github.com/ashtuchkin/iconv-lite){target=_blank} | 0.4.24 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 88 | [ieee754](https://github.com/feross/ieee754){target=_blank} | 1.2.1 | [BSD-3-Clause](https://choosealicense.com/licenses/bsd-3-clause){target=_blank} | +| 89 | [inflight](https://github.com/npm/inflight){target=_blank} | 1.0.6 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 90 | [inherits](https://github.com/isaacs/inherits){target=_blank} | 2.0.4 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 91 | [ipaddr.js](https://github.com/whitequark/ipaddr.js){target=_blank} | 1.9.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 92 | [is-absolute](https://github.com/jonschlinkert/is-absolute){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 93 | [is-binary-path](https://github.com/sindresorhus/is-binary-path){target=_blank} | 2.1.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 94 | [is-docker](https://github.com/sindresorhus/is-docker){target=_blank} | 2.2.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 95 | [is-extglob](https://github.com/jonschlinkert/is-extglob){target=_blank} | 2.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 96 | [is-glob](https://github.com/micromatch/is-glob){target=_blank} | 4.0.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 97 | [is-number](https://github.com/jonschlinkert/is-number){target=_blank} | 7.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 98 | [is-relative](https://github.com/jonschlinkert/is-relative){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 99 | [is-unc-path](https://github.com/jonschlinkert/is-unc-path){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 100 | [is-windows](https://github.com/jonschlinkert/is-windows){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 101 | [is-wsl](https://github.com/sindresorhus/is-wsl){target=_blank} | 2.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 102 | [isarray](https://github.com/juliangruber/isarray){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 103 | [isexe](https://github.com/isaacs/isexe){target=_blank} | 2.0.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 104 | [isnumber](https://github.com/brycebaril/node-isnumber){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 105 | [jake](https://github.com/jakejs/jake){target=_blank} | 10.8.5 | [Apache-2.0](https://choosealicense.com/licenses/apache-2.0){target=_blank} | +| 106 | [js-yaml](https://github.com/nodeca/js-yaml){target=_blank} | 4.1.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 107 | [json-diff](https://github.com/andreyvit/json-diff){target=_blank} | 1.0.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 108 | [json-stable-stringify](https://github.com/ljharb/json-stable-stringify){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 109 | [jsonfile](https://github.com/jprichardson/node-jsonfile){target=_blank} | 6.1.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 110 | [jsonify](https://github.com/ljharb/jsonify){target=_blank} | 0.0.1 | [Public](){target=_blank} | [Domain](){target=_blank} | -| 110 | [klaw-sync](https://github.com/manidlou/node-klaw-sync){target=_blank} | 6.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 111 | [lazystream](https://github.com/jpommerening/node-lazystream){target=_blank} | 1.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 112 | [lodash](https://github.com/lodash/lodash){target=_blank} | 4.17.21 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 113 | [lodash.defaults](https://github.com/lodash/lodash){target=_blank} | 4.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 114 | [lodash.difference](https://github.com/lodash/lodash){target=_blank} | 4.5.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 115 | [lodash.flatten](https://github.com/lodash/lodash){target=_blank} | 4.4.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 116 | [lodash.isplainobject](https://github.com/lodash/lodash){target=_blank} | 4.0.6 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 117 | [lodash.union](https://github.com/lodash/lodash){target=_blank} | 4.6.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 118 | [logic-solver](https://github.com/meteor/logic-solver){target=_blank} | 2.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 119 | [lru-cache](https://github.com/isaacs/node-lru-cache){target=_blank} | 9.0.3 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 120 | [media-typer](https://github.com/jshttp/media-typer){target=_blank} | 0.3.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 121 | [merge-descriptors](https://github.com/component/merge-descriptors){target=_blank} | 1.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 122 | [methods](https://github.com/jshttp/methods){target=_blank} | 1.1.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 123 | [micromatch](https://github.com/micromatch/micromatch){target=_blank} | 4.0.5 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 124 | [mime](https://github.com/broofa/node-mime){target=_blank} | 1.6.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 125 | [mime-db](https://github.com/jshttp/mime-db){target=_blank} | 1.52.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 126 | [mime-types](https://github.com/jshttp/mime-types){target=_blank} | 2.1.35 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 127 | [minimatch](https://github.com/isaacs/minimatch){target=_blank} | 9.0.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 128 | [minimist](https://github.com/minimistjs/minimist){target=_blank} | 1.2.8 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 129 | [minipass](https://github.com/isaacs/minipass){target=_blank} | 5.0.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 130 | [ms](https://github.com/vercel/ms){target=_blank} | 2.1.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 131 | [negotiator](https://github.com/jshttp/negotiator){target=_blank} | 0.6.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 132 | [node-cron](https://github.com/merencia/node-cron){target=_blank} | 3.0.2 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 133 | [normalize-path](https://github.com/jonschlinkert/normalize-path){target=_blank} | 3.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 134 | [object-assign](https://github.com/sindresorhus/object-assign){target=_blank} | 4.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 135 | [object-inspect](https://github.com/inspect-js/object-inspect){target=_blank} | 1.12.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 136 | [ohm-js](https://github.com/harc/ohm){target=_blank} | 16.4.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 137 | [on-finished](https://github.com/jshttp/on-finished){target=_blank} | 2.4.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 138 | [once](https://github.com/isaacs/once){target=_blank} | 1.4.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 139 | [open](https://github.com/sindresorhus/open){target=_blank} | 7.4.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 140 | [opentosca-vintner](https://github.com/OpenTOSCA/opentosca-vintner){target=_blank} | 0.1.4 | [Apache-2.0](https://choosealicense.com/licenses/apache-2.0){target=_blank} | -| 141 | [os-tmpdir](https://github.com/sindresorhus/os-tmpdir){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 142 | [papaparse](https://github.com/mholt/PapaParse){target=_blank} | 5.4.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 143 | [parseurl](https://github.com/pillarjs/parseurl){target=_blank} | 1.3.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 144 | [patch-package](https://github.com/ds300/patch-package){target=_blank} | 8.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 145 | [path-is-absolute](https://github.com/sindresorhus/path-is-absolute){target=_blank} | 1.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 146 | [path-key](https://github.com/sindresorhus/path-key){target=_blank} | 3.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 147 | [path-scurry](https://github.com/isaacs/path-walker){target=_blank} | 1.7.0 | [BlueOak-1.0.0](https://blueoakcouncil.org/license/1.0.0){target=_blank} | -| 148 | [path-to-regexp](https://github.com/component/path-to-regexp){target=_blank} | 0.1.7 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 149 | [pend](https://github.com/andrewrk/node-pend){target=_blank} | 1.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 150 | [picomatch](https://github.com/micromatch/picomatch){target=_blank} | 2.3.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 151 | [process-nextick-args](https://github.com/calvinmetcalf/process-nextick-args){target=_blank} | 2.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 152 | [proxy-addr](https://github.com/jshttp/proxy-addr){target=_blank} | 2.0.7 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 153 | [pump](https://github.com/mafintosh/pump){target=_blank} | 3.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 154 | [qs](https://github.com/ljharb/qs){target=_blank} | 6.11.0 | [BSD-3-Clause](https://choosealicense.com/licenses/bsd-3-clause){target=_blank} | -| 155 | [range-parser](https://github.com/jshttp/range-parser){target=_blank} | 1.2.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 156 | [raw-body](https://github.com/stream-utils/raw-body){target=_blank} | 2.5.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 157 | [readable-stream](https://github.com/nodejs/readable-stream){target=_blank} | 3.6.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 158 | [readdir-enhanced](https://github.com/bigstickcarpet/readdir-enhanced){target=_blank} | 1.5.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 159 | [readdir-glob](https://github.com/Yqnn/node-readdir-glob){target=_blank} | 1.1.3 | [Apache-2.0](https://choosealicense.com/licenses/apache-2.0){target=_blank} | -| 160 | [readdirp](https://github.com/paulmillr/readdirp){target=_blank} | 3.6.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 161 | [regression](https://github.com/Tom-Alexander/regression-js){target=_blank} | 2.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 162 | [rimraf](https://github.com/isaacs/rimraf){target=_blank} | 2.7.1 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 163 | [safe-buffer](https://github.com/feross/safe-buffer){target=_blank} | 5.2.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 164 | [safer-buffer](https://github.com/ChALkeR/safer-buffer){target=_blank} | 2.1.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 165 | [sax](https://github.com/isaacs/sax-js){target=_blank} | 1.2.4 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 166 | [semver](https://github.com/npm/node-semver){target=_blank} | 7.5.4 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 167 | [send](https://github.com/pillarjs/send){target=_blank} | 0.18.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 168 | [serve-static](https://github.com/expressjs/serve-static){target=_blank} | 1.15.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 169 | [setprototypeof](https://github.com/wesleytodd/setprototypeof){target=_blank} | 1.2.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 170 | [shebang-command](https://github.com/kevva/shebang-command){target=_blank} | 2.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 171 | [shebang-regex](https://github.com/sindresorhus/shebang-regex){target=_blank} | 3.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 172 | [side-channel](https://github.com/ljharb/side-channel){target=_blank} | 1.0.4 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 173 | [slash](https://github.com/sindresorhus/slash){target=_blank} | 2.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 174 | [stats-lite](https://github.com/brycebaril/node-stats-lite){target=_blank} | 2.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 175 | [statuses](https://github.com/jshttp/statuses){target=_blank} | 2.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 176 | [string_decoder](https://github.com/nodejs/string_decoder){target=_blank} | 1.3.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 177 | [supports-color](https://github.com/chalk/supports-color){target=_blank} | 7.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 178 | [sync-directory](https://github.com/hoperyy/sync-directory){target=_blank} | 6.0.4 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 179 | [systeminformation](https://github.com/sebhildebrandt/systeminformation){target=_blank} | 5.21.8 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 180 | [tar-stream](https://github.com/mafintosh/tar-stream){target=_blank} | 2.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 181 | [tmp](https://github.com/raszi/node-tmp){target=_blank} | 0.0.33 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 182 | [to-regex-range](https://github.com/micromatch/to-regex-range){target=_blank} | 5.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 183 | [toidentifier](https://github.com/component/toidentifier){target=_blank} | 1.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 184 | [tslib](https://github.com/Microsoft/tslib){target=_blank} | 2.5.0 | [0BSD](https://choosealicense.com/licenses/0bsd){target=_blank} | -| 185 | [type-is](https://github.com/jshttp/type-is){target=_blank} | 1.6.18 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 186 | [unc-path-regex](https://github.com/regexhq/unc-path-regex){target=_blank} | 0.1.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 187 | [underscore](https://github.com/jashkenas/underscore){target=_blank} | 1.13.6 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 188 | [universalify](https://github.com/RyanZim/universalify){target=_blank} | 2.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 189 | [unpipe](https://github.com/stream-utils/unpipe){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 190 | [util-deprecate](https://github.com/TooTallNate/util-deprecate){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 191 | [utils-merge](https://github.com/jaredhanson/utils-merge){target=_blank} | 1.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 192 | [uuid](https://github.com/uuidjs/uuid){target=_blank} | 9.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 193 | [vary](https://github.com/jshttp/vary){target=_blank} | 1.1.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 194 | [which](https://github.com/isaacs/node-which){target=_blank} | 2.0.2 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 195 | [wordwrap](https://github.com/substack/node-wordwrap){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 196 | [wrappy](https://github.com/npm/wrappy){target=_blank} | 1.0.2 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 197 | [xml2js](https://github.com/Leonidas-from-XIV/node-xml2js){target=_blank} | 0.5.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 198 | [xmlbuilder](https://github.com/oozcitak/xmlbuilder-js){target=_blank} | 11.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 199 | [yallist](https://github.com/isaacs/yallist){target=_blank} | 4.0.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 200 | [yaml](https://github.com/eemeli/yaml){target=_blank} | 2.3.2 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | -| 201 | [yauzl](https://github.com/thejoshwolfe/yauzl){target=_blank} | 2.10.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | -| 202 | [zip-stream](https://github.com/archiverjs/node-zip-stream){target=_blank} | 4.1.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 111 | [klaw-sync](https://github.com/manidlou/node-klaw-sync){target=_blank} | 6.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 112 | [lazystream](https://github.com/jpommerening/node-lazystream){target=_blank} | 1.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 113 | [lnk](https://github.com/schnittstabil/lnk){target=_blank} | 1.1.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 114 | [lodash](https://github.com/lodash/lodash){target=_blank} | 4.17.21 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 115 | [lodash.defaults](https://github.com/lodash/lodash){target=_blank} | 4.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 116 | [lodash.difference](https://github.com/lodash/lodash){target=_blank} | 4.5.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 117 | [lodash.flatten](https://github.com/lodash/lodash){target=_blank} | 4.4.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 118 | [lodash.isplainobject](https://github.com/lodash/lodash){target=_blank} | 4.0.6 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 119 | [lodash.union](https://github.com/lodash/lodash){target=_blank} | 4.6.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 120 | [logic-solver](https://github.com/meteor/logic-solver){target=_blank} | 2.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 121 | [lru-cache](https://github.com/isaacs/node-lru-cache){target=_blank} | 9.0.3 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 122 | [media-typer](https://github.com/jshttp/media-typer){target=_blank} | 0.3.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 123 | [merge-descriptors](https://github.com/component/merge-descriptors){target=_blank} | 1.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 124 | [methods](https://github.com/jshttp/methods){target=_blank} | 1.1.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 125 | [micromatch](https://github.com/micromatch/micromatch){target=_blank} | 4.0.5 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 126 | [mime](https://github.com/broofa/node-mime){target=_blank} | 1.6.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 127 | [mime-db](https://github.com/jshttp/mime-db){target=_blank} | 1.52.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 128 | [mime-types](https://github.com/jshttp/mime-types){target=_blank} | 2.1.35 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 129 | [minimatch](https://github.com/isaacs/minimatch){target=_blank} | 9.0.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 130 | [minimist](https://github.com/minimistjs/minimist){target=_blank} | 1.2.8 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 131 | [minipass](https://github.com/isaacs/minipass){target=_blank} | 5.0.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 132 | [mkdirp](https://github.com/substack/node-mkdirp){target=_blank} | 0.5.6 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 133 | [ms](https://github.com/vercel/ms){target=_blank} | 2.1.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 134 | [negotiator](https://github.com/jshttp/negotiator){target=_blank} | 0.6.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 135 | [node-cron](https://github.com/merencia/node-cron){target=_blank} | 3.0.2 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 136 | [normalize-path](https://github.com/jonschlinkert/normalize-path){target=_blank} | 3.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 137 | [object-assign](https://github.com/sindresorhus/object-assign){target=_blank} | 4.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 138 | [object-inspect](https://github.com/inspect-js/object-inspect){target=_blank} | 1.12.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 139 | [ohm-js](https://github.com/harc/ohm){target=_blank} | 16.4.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 140 | [on-finished](https://github.com/jshttp/on-finished){target=_blank} | 2.4.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 141 | [once](https://github.com/isaacs/once){target=_blank} | 1.4.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 142 | [open](https://github.com/sindresorhus/open){target=_blank} | 7.4.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 143 | [opentosca-vintner](https://github.com/OpenTOSCA/opentosca-vintner){target=_blank} | 0.1.4 | [Apache-2.0](https://choosealicense.com/licenses/apache-2.0){target=_blank} | +| 144 | [os-tmpdir](https://github.com/sindresorhus/os-tmpdir){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 145 | [papaparse](https://github.com/mholt/PapaParse){target=_blank} | 5.4.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 146 | [parseurl](https://github.com/pillarjs/parseurl){target=_blank} | 1.3.3 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 147 | [patch-package](https://github.com/ds300/patch-package){target=_blank} | 8.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 148 | [path-is-absolute](https://github.com/sindresorhus/path-is-absolute){target=_blank} | 1.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 149 | [path-key](https://github.com/sindresorhus/path-key){target=_blank} | 3.1.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 150 | [path-scurry](https://github.com/isaacs/path-walker){target=_blank} | 1.7.0 | [BlueOak-1.0.0](https://blueoakcouncil.org/license/1.0.0){target=_blank} | +| 151 | [path-to-regexp](https://github.com/component/path-to-regexp){target=_blank} | 0.1.7 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 152 | [pend](https://github.com/andrewrk/node-pend){target=_blank} | 1.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 153 | [picomatch](https://github.com/micromatch/picomatch){target=_blank} | 2.3.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 154 | [pify](https://github.com/sindresorhus/pify){target=_blank} | 2.3.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 155 | [process-nextick-args](https://github.com/calvinmetcalf/process-nextick-args){target=_blank} | 2.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 156 | [proxy-addr](https://github.com/jshttp/proxy-addr){target=_blank} | 2.0.7 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 157 | [pump](https://github.com/mafintosh/pump){target=_blank} | 3.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 158 | [qs](https://github.com/ljharb/qs){target=_blank} | 6.11.0 | [BSD-3-Clause](https://choosealicense.com/licenses/bsd-3-clause){target=_blank} | +| 159 | [range-parser](https://github.com/jshttp/range-parser){target=_blank} | 1.2.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 160 | [raw-body](https://github.com/stream-utils/raw-body){target=_blank} | 2.5.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 161 | [readable-stream](https://github.com/nodejs/readable-stream){target=_blank} | 3.6.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 162 | [readdir-enhanced](https://github.com/bigstickcarpet/readdir-enhanced){target=_blank} | 1.5.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 163 | [readdir-glob](https://github.com/Yqnn/node-readdir-glob){target=_blank} | 1.1.3 | [Apache-2.0](https://choosealicense.com/licenses/apache-2.0){target=_blank} | +| 164 | [readdirp](https://github.com/paulmillr/readdirp){target=_blank} | 3.6.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 165 | [regression](https://github.com/Tom-Alexander/regression-js){target=_blank} | 2.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 166 | [rimraf](https://github.com/isaacs/rimraf){target=_blank} | 2.7.1 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 167 | [safe-buffer](https://github.com/feross/safe-buffer){target=_blank} | 5.2.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 168 | [safer-buffer](https://github.com/ChALkeR/safer-buffer){target=_blank} | 2.1.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 169 | [sax](https://github.com/isaacs/sax-js){target=_blank} | 1.2.4 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 170 | [semver](https://github.com/npm/node-semver){target=_blank} | 7.5.4 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 171 | [send](https://github.com/pillarjs/send){target=_blank} | 0.18.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 172 | [serve-static](https://github.com/expressjs/serve-static){target=_blank} | 1.15.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 173 | [setprototypeof](https://github.com/wesleytodd/setprototypeof){target=_blank} | 1.2.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 174 | [shebang-command](https://github.com/kevva/shebang-command){target=_blank} | 2.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 175 | [shebang-regex](https://github.com/sindresorhus/shebang-regex){target=_blank} | 3.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 176 | [side-channel](https://github.com/ljharb/side-channel){target=_blank} | 1.0.4 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 177 | [slash](https://github.com/sindresorhus/slash){target=_blank} | 2.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 178 | [stats-lite](https://github.com/brycebaril/node-stats-lite){target=_blank} | 2.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 179 | [statuses](https://github.com/jshttp/statuses){target=_blank} | 2.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 180 | [string_decoder](https://github.com/nodejs/string_decoder){target=_blank} | 1.3.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 181 | [supports-color](https://github.com/chalk/supports-color){target=_blank} | 7.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 182 | [sync-directory](https://github.com/hoperyy/sync-directory){target=_blank} | 6.0.4 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 183 | [systeminformation](https://github.com/sebhildebrandt/systeminformation){target=_blank} | 5.21.8 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 184 | [tar-stream](https://github.com/mafintosh/tar-stream){target=_blank} | 2.2.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 185 | [tmp](https://github.com/raszi/node-tmp){target=_blank} | 0.0.33 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 186 | [to-regex-range](https://github.com/micromatch/to-regex-range){target=_blank} | 5.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 187 | [toidentifier](https://github.com/component/toidentifier){target=_blank} | 1.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 188 | [tslib](https://github.com/Microsoft/tslib){target=_blank} | 2.5.0 | [0BSD](https://choosealicense.com/licenses/0bsd){target=_blank} | +| 189 | [type-is](https://github.com/jshttp/type-is){target=_blank} | 1.6.18 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 190 | [unc-path-regex](https://github.com/regexhq/unc-path-regex){target=_blank} | 0.1.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 191 | [underscore](https://github.com/jashkenas/underscore){target=_blank} | 1.13.6 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 192 | [universalify](https://github.com/RyanZim/universalify){target=_blank} | 2.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 193 | [unpipe](https://github.com/stream-utils/unpipe){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 194 | [util-deprecate](https://github.com/TooTallNate/util-deprecate){target=_blank} | 1.0.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 195 | [utils-merge](https://github.com/jaredhanson/utils-merge){target=_blank} | 1.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 196 | [uuid](https://github.com/uuidjs/uuid){target=_blank} | 9.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 197 | [vary](https://github.com/jshttp/vary){target=_blank} | 1.1.2 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 198 | [which](https://github.com/isaacs/node-which){target=_blank} | 2.0.2 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 199 | [wordwrap](https://github.com/substack/node-wordwrap){target=_blank} | 1.0.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 200 | [wrappy](https://github.com/npm/wrappy){target=_blank} | 1.0.2 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 201 | [xml2js](https://github.com/Leonidas-from-XIV/node-xml2js){target=_blank} | 0.5.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 202 | [xmlbuilder](https://github.com/oozcitak/xmlbuilder-js){target=_blank} | 11.0.1 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 203 | [yallist](https://github.com/isaacs/yallist){target=_blank} | 4.0.0 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 204 | [yaml](https://github.com/eemeli/yaml){target=_blank} | 2.3.2 | [ISC](https://choosealicense.com/licenses/isc){target=_blank} | +| 205 | [yauzl](https://github.com/thejoshwolfe/yauzl){target=_blank} | 2.10.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | +| 206 | [zip-stream](https://github.com/archiverjs/node-zip-stream){target=_blank} | 4.1.0 | [MIT](https://choosealicense.com/licenses/mit){target=_blank} | We fixed the following issues by patching the dependencies. diff --git a/docs/docs/interface.md b/docs/docs/interface.md index aeb9e8795d..e201672f76 100644 --- a/docs/docs/interface.md +++ b/docs/docs/interface.md @@ -1518,6 +1518,7 @@ validates variability-resolved service template | instance | true | string | instance name | | inputs | false | string | path to the deployment inputs | | verbose | false | boolean | verbose | +| dry | false | boolean | dry run | ## vintner orchestrators attest @@ -2430,7 +2431,8 @@ pull template dependencies | Option | Mandatory | Type | Description | | --- | --- | --- | --- | -| template | true | string | path to service template | +| template | true | string | path to service template directory | +| link | false | boolean | create symbolic links instead of copying files (default: false) | ## vintner template puml topology diff --git a/docs/docs/orchestrators.md b/docs/docs/orchestrators.md index dc6ea23f96..54b64d8f91 100644 --- a/docs/docs/orchestrators.md +++ b/docs/docs/orchestrators.md @@ -103,6 +103,21 @@ The orchestrators provide more features, see [TOSSS](https://tosss.opentosca.org | Access node instance attributes | :material-check: | :material-close: | +## Deployment Technologies + +Under the scene, we are using the following deployment technologies. + +| Technology | Version | +|------------------------------|---------| +| ansible (pip) | 4.10.0 | +| google-cloud-cli (apt) | 432.0.0 | +| kubernetes (pip) | 24.2.0 | +| openshift (pip) | 0.13.2 | +| openstacksdk (pip) | 0.61 | +| python-openstackclient (pip) | 6.0.0 | +| terraform (apt) | 1.4.6 | + + ## Known Limitations - xOpera version 0.6.9 should be used. xOpera version 0.7.0 does not parse the templates as expected, see issues [#257](https://github.com/xlab-si/xopera-opera/issues/257){target=_blank}, diff --git a/docs/docs/variability4tosca/specification/index.md b/docs/docs/variability4tosca/specification/index.md index 3006648fff..7de34b575b 100644 --- a/docs/docs/variability4tosca/specification/index.md +++ b/docs/docs/variability4tosca/specification/index.md @@ -56,7 +56,7 @@ A variability definition defines variability inputs, variability presets, variab | expressions | false | Map(String, VariabilityExpression) | An optional map of variability expressions. | | options | false | Map(String, Boolean) | An optional map of variability options. | | type_specific_conditions | false | String | List(TypeSpecificDefaultCondition) | An optional definition of type-specific default conditions. If string, then treated as relative file to import (default: "./type-specific-conditions.yaml") | -| technology_assignment_rules | false | String | Map(String, TechnologyAssignmentRule) | An optional definition of technology assignment rules. If string, then treated as relative file to import (default: "./rules.yaml"). | +| technology_assignment_rules | false | String | Map(String, TechnologyAssignmentRule) | An optional definition of technology assignment rules. If string, then treated as relative file to import (default: ["./rules.yaml", "./lib/rules.yaml"]). | | plugins | false | PluginDefinition | An optional definition of plugins. | The following non-normative and incomplete example contains a variability definition which declares the variability @@ -220,8 +220,6 @@ The following options are used to configure checks. ### Solver Options -_This is an experimental feature._ - The following options are used to configure the solver. | Keyname | Mandatory | Type | Default | Description | @@ -252,8 +250,6 @@ The following options are used to configure constraints. ### Pruning Modes -_This is an experimental feature._ - There are several predefined pruning modes which provide different useful combinations of default conditions and the pruning of elements that can be directly used. - `manual`: no default or pruning conditions are enabled at all @@ -335,12 +331,13 @@ _Conditional types conflict with this feature!_ Technology assignment rules can be defined to automatically select a deployment technology for a component. A technology assignment rule is defined as follows. -| Keyname | Mandatory | Type | Description | -|------------|-----------|--------------------------------------------------------|-------------------------------------------------------------------------| -| component | true | String | The type of the component to which the technology can be assigned. | -| host | false | String | The type of the host of the component which the technology requires. | -| conditions | false | VariabilityCondition | List(VariabilityCondition) | The conditions under which a technology can be assigned to a component. | -| weight | false | Number | The weight which is minimized (default is 1). | +| Keyname | Mandatory | Type | Description | +|-------------|-----------|--------------------------------------------------------|---------------------------------------------------------------------------------------------------------------| +| component | true | String | The type of the component to which the technology can be assigned. | +| host | false | String | The type of the host of the component which the technology requires. | +| conditions | false | VariabilityCondition | List(VariabilityCondition) | The conditions under which a technology can be assigned to a component. | +| weight | false | Number | The weight which is minimized (default is 1). | +| assign | false | String | Configure the node type that is assigned (default: `${current_type}.${technology_name}.${host_type_prefix}`). | | | For example, the node type `application` can be deployed using the deployment technology `terraform` if the host is of type `terraform_host`. @@ -451,7 +448,7 @@ A node template can also hold conditional types, artifact, and properties. | pruning | false | Boolean | Enable the pruning for this element. This overrides the variability options of the variable topology template. | | consistency_pruning | false | Boolean | Enable the consistency pruning for this element. Pruning must be enabled for this element. This overrides the variability options of the variable topology template. | | semantic_pruning | false | Boolean | Enable the semantic pruning for this element. Pruning must be enabled for this element. This overrides the variability options of the variable topology template. | -| weight | false | Boolean | Non-Negative Number | Configure the weight of this element used during optimization (default is 1). _This is an experimental feature._ | +| weight | false | Boolean | Non-Negative Number | Configure the weight of this element used during optimization (default is 1). | | implies | false | List(Tuple(Target: VariabilityCondition, Condition?: VariabilityCondition)) | An optional list of implications following the pattern `element implies target` or `(element and condition) implies target`. | | technology | false | List(Map(String, TechnologyTemplate){single}) | An optional conditional assignment of deployment technologies. | @@ -479,6 +476,8 @@ These conditions must hold otherwise the respective technology template is not p | pruning | false | Boolean | Enable the pruning for this element. This overrides the variability options of the variable topology template. | | consistency_pruning | false | Boolean | Enable the consistency pruning for this element. Pruning must be enabled for this element. This overrides the variability options of the variable topology template. | | semantic_pruning | false | Boolean | Enable the semantic pruning for this element. Pruning must be enabled for this element. This overrides the variability options of the variable topology template. | +| weight | false | Boolean | Non-Negative Number | Configure the weight of this element used during optimization (default is 1). | +| assign | false | String | Configure the node type that is assigned (default: `${current_type}.${technology_name}.${host_type_prefix}`). | | | ## Type Assignment @@ -963,7 +962,7 @@ export type TechnologyPluginBuilder = { ```typescript linenums="1" export type TechnologyPlugin = { - assign: (node: Node) => ConditionalTechnologyAssignment[] + assign: (node: Node) => {[technology: string]: TechnologyTemplate}[] } ``` @@ -1079,13 +1078,12 @@ However, type-specific default conditions are defined per type, e.g., node type, ### Optimization -_This is an experimental feature._ - -The variability-resolved service template can be optimized regarding minimal weight of node templates. +The variability-resolved service template can be optimized regarding the weight of node templates. The default weight of a node template is 1. -Thus, per default, the variability-resolved service template is optimized regarding the minimal number of node templates. +Per default, the variability-resolved service template is optimized regarding the minimal weight/ number of node templates. The primary intention is to minimize the deployment complexity, but optimization could be also used, e.g., to minimize overall costs. The weight of a node template can be configured in its definition. +Moreover, technology selection can be optimized. ## Element System diff --git a/docs/docs/variability4tosca/tests/introduction.md b/docs/docs/variability4tosca/tests/introduction.md index 88d8d68155..7ad46c0ba6 100644 --- a/docs/docs/variability4tosca/tests/introduction.md +++ b/docs/docs/variability4tosca/tests/introduction.md @@ -207,8 +207,8 @@ processing. | 182 | [other-preset](./test-other-preset.md) | | 183 | [other-presets](./test-other-presets.md) | | 184 | [other-throw-CONTAINER](./test-other-throw-CONTAINER.md) | -| 185 | [other-throw-not-unique](./test-other-throw-not-unique.md) | -| 186 | [other-throw-SELF](./test-other-throw-SELF.md) | +| 185 | [other-throw-SELF](./test-other-throw-SELF.md) | +| 186 | [other-throw-not-unique](./test-other-throw-not-unique.md) | | 187 | [Operator "concat"](./test-other-token.md) | | 188 | [Get Variability Expression](./test-other-value-expression.md) | | 189 | [Get Variability Input](./test-other-variability-input.md) | diff --git a/docs/docs/variability4tosca/tests/test-technologies-ambiguous-disabled.md b/docs/docs/variability4tosca/tests/test-technologies-ambiguous-disabled.md index 1605215728..b1083dd0cf 100644 --- a/docs/docs/variability4tosca/tests/test-technologies-ambiguous-disabled.md +++ b/docs/docs/variability4tosca/tests/test-technologies-ambiguous-disabled.md @@ -35,6 +35,6 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.ansible + type: container.ansible.container ``` diff --git a/docs/docs/variability4tosca/tests/test-technologies-conditional.md b/docs/docs/variability4tosca/tests/test-technologies-conditional.md index 7adb237de8..ab041606a9 100644 --- a/docs/docs/variability4tosca/tests/test-technologies-conditional.md +++ b/docs/docs/variability4tosca/tests/test-technologies-conditional.md @@ -34,6 +34,6 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.ansible + type: container.ansible.container ``` diff --git a/docs/docs/variability4tosca/tests/test-technologies-default-true.md b/docs/docs/variability4tosca/tests/test-technologies-default-true.md index 42791bfb19..ec6b4d4297 100644 --- a/docs/docs/variability4tosca/tests/test-technologies-default-true.md +++ b/docs/docs/variability4tosca/tests/test-technologies-default-true.md @@ -34,6 +34,6 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.terraform + type: container.terraform.container ``` diff --git a/docs/docs/variability4tosca/tests/test-technologies-lowercase.md b/docs/docs/variability4tosca/tests/test-technologies-lowercase.md index 2a599bdb17..00ef47bc80 100644 --- a/docs/docs/variability4tosca/tests/test-technologies-lowercase.md +++ b/docs/docs/variability4tosca/tests/test-technologies-lowercase.md @@ -32,6 +32,6 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.ansible + type: container.ansible.container ``` diff --git a/docs/docs/variability4tosca/tests/test-technologies-optimization-double.md b/docs/docs/variability4tosca/tests/test-technologies-optimization-double.md index 0fa3e28097..0dc09cd68e 100644 --- a/docs/docs/variability4tosca/tests/test-technologies-optimization-double.md +++ b/docs/docs/variability4tosca/tests/test-technologies-optimization-double.md @@ -56,8 +56,8 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.ansible + type: container.ansible.container another: - type: another.ansible + type: another.ansible.another ``` diff --git a/docs/docs/variability4tosca/tests/test-technologies-optimization-order.md b/docs/docs/variability4tosca/tests/test-technologies-optimization-order.md index 92ca4af213..4d9a741a35 100644 --- a/docs/docs/variability4tosca/tests/test-technologies-optimization-order.md +++ b/docs/docs/variability4tosca/tests/test-technologies-optimization-order.md @@ -45,8 +45,8 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.ansible + type: container.ansible.container another: - type: another.ansible + type: another.ansible.another ``` diff --git a/docs/docs/variability4tosca/tests/test-technologies-optimization-weight.md b/docs/docs/variability4tosca/tests/test-technologies-optimization-weight.md index 2a85772349..c05f638b5f 100644 --- a/docs/docs/variability4tosca/tests/test-technologies-optimization-weight.md +++ b/docs/docs/variability4tosca/tests/test-technologies-optimization-weight.md @@ -44,8 +44,8 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.terraform + type: container.terraform.container another: - type: another.ansible + type: another.ansible.another ``` diff --git a/docs/docs/variability4tosca/tests/test-technologies-optimization.md b/docs/docs/variability4tosca/tests/test-technologies-optimization.md index 8491435a01..568204fe92 100644 --- a/docs/docs/variability4tosca/tests/test-technologies-optimization.md +++ b/docs/docs/variability4tosca/tests/test-technologies-optimization.md @@ -42,8 +42,8 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.ansible + type: container.ansible.container another: - type: another.ansible + type: another.ansible.another ``` diff --git a/docs/docs/variability4tosca/tests/test-technologies-rules.md b/docs/docs/variability4tosca/tests/test-technologies-rules.md index f48f6d9e56..3447a88b26 100644 --- a/docs/docs/variability4tosca/tests/test-technologies-rules.md +++ b/docs/docs/variability4tosca/tests/test-technologies-rules.md @@ -76,17 +76,17 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: application: - type: application.terraform + type: application.terraform.ansible_terraform_host requirements: - host: ansible_terraform_host - database: database ansible_terraform_host: type: ansible_terraform_host database: - type: database.terraform + type: database.terraform.dbms requirements: - host: dbms dbms: - type: dbms.terraform + type: dbms.terraform.dbms ``` diff --git a/docs/docs/variability4tosca/tests/test-technologies-unique-disabled.md b/docs/docs/variability4tosca/tests/test-technologies-unique-disabled.md index ec8ace07c0..b95d617fed 100644 --- a/docs/docs/variability4tosca/tests/test-technologies-unique-disabled.md +++ b/docs/docs/variability4tosca/tests/test-technologies-unique-disabled.md @@ -38,6 +38,6 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.puppet + type: container.puppet.container ``` diff --git a/docs/overrides/overrides/features.html b/docs/overrides/overrides/features.html index 235cf276f2..0498868400 100644 --- a/docs/overrides/overrides/features.html +++ b/docs/overrides/overrides/features.html @@ -136,7 +136,7 @@ "Open Source", "Apache 2.0", "Contributor Conveneant 2.0", - "Over 475 Tests", + "Over 500 Tests", "Weekly Integration Tests", "Code Quality Analysis", ] diff --git a/examples/unfurl-artifacts/scripts/reimport.sh b/examples/unfurl-artifacts/scripts/reimport.sh index 9a94ac1be5..9d447da074 100644 --- a/examples/unfurl-artifacts/scripts/reimport.sh +++ b/examples/unfurl-artifacts/scripts/reimport.sh @@ -11,4 +11,4 @@ $VINTNER templates import --template ${TEMPLATE_NAME} --path ${TEMPLATE_DIR} $VINTNER instances init --instance ${TEMPLATE_NAME} --template ${TEMPLATE_NAME} $VINTNER instances resolve --instance ${TEMPLATE_NAME} --presets ${DEPLOYMENT_VARIANT} $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 +$VINTNER instances deploy --instance ${TEMPLATE_NAME} --inputs ${TEMPLATE_DIR}/deployment-inputs.ignored.yaml diff --git a/examples/unfurl-technology-automated-counting/.gitignore b/examples/unfurl-technology-automated-counting/.gitignore new file mode 100644 index 0000000000..4fe5ca855c --- /dev/null +++ b/examples/unfurl-technology-automated-counting/.gitignore @@ -0,0 +1,2 @@ +files +lib diff --git a/examples/unfurl-technology-automated-counting/config.yaml b/examples/unfurl-technology-automated-counting/config.yaml new file mode 100644 index 0000000000..8b7a206366 --- /dev/null +++ b/examples/unfurl-technology-automated-counting/config.yaml @@ -0,0 +1,3 @@ +dependencies: + - source: ../unfurl-technology-automated-weighted/lib + - source: ../unfurl-technology-automated-weighted/files diff --git a/examples/unfurl-technology-automated-counting/stats.sh b/examples/unfurl-technology-automated-counting/stats.sh new file mode 100644 index 0000000000..7cb56a56ac --- /dev/null +++ b/examples/unfurl-technology-automated-counting/stats.sh @@ -0,0 +1,4 @@ +#!/usr/bin/bash +set -e + +yarn cli template stats --template ${PWD}/variable-service-template.yaml \ No newline at end of file diff --git a/examples/unfurl-technology-automated-counting/tests/elastic/expected.yaml b/examples/unfurl-technology-automated-counting/tests/elastic/expected.yaml new file mode 100644 index 0000000000..f6cfe08713 --- /dev/null +++ b/examples/unfurl-technology-automated-counting/tests/elastic/expected.yaml @@ -0,0 +1,53 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + gcp_region: + type: string + default: europe-west3 + + gcp_service_account_file: + type: string + default: /home/stoetzms/gcp/stoetzms-387808-2ec1cf865c76.json + + gcp_project: + type: string + default: stoetzms-387808 + + node_templates: + shop: + type: shop.component.ansible.gcp + properties: + application_name: unfurl-technology + DB_NAME: unfurl-technology + DB_USERNAME: root + DB_PASSWORD: {get_input: database_password} + DB_DIALECT: mysql + DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: database + - host: gcp_runtime + + database: + type: mysql.database.ansible.gcp + properties: + database_name: unfurl-technology + requirements: + - host: gcp_dbms + + gcp_dbms: + type: gcp.cloud_sql.ansible.gcp + properties: + instance_name: unfurl-technology + root_password: {get_input: database_password} + + gcp_runtime: + type: gcp.app_engine.ansible.gcp diff --git a/examples/unfurl-technology-automated-counting/tests/elastic/test.yaml b/examples/unfurl-technology-automated-counting/tests/elastic/test.yaml new file mode 100644 index 0000000000..ce4eae556b --- /dev/null +++ b/examples/unfurl-technology-automated-counting/tests/elastic/test.yaml @@ -0,0 +1 @@ +presets: elastic diff --git a/examples/unfurl-technology-automated-counting/tests/static-large/expected.yaml b/examples/unfurl-technology-automated-counting/tests/static-large/expected.yaml new file mode 100644 index 0000000000..2f693871c7 --- /dev/null +++ b/examples/unfurl-technology-automated-counting/tests/static-large/expected.yaml @@ -0,0 +1,90 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + os_network: + type: string + default: public-belwue + + os_ssh_key_name: + type: string + default: default + + os_ssh_user: + type: string + default: ubuntu + + os_ssh_key_file: + type: string + default: /home/stoetzms/.ssh/bw-cloud--default + + os_region_name: + type: string + default: Mannheim + + os_auth_type: + type: string + default: v3applicationcredential + + os_auth_url: + type: string + default: https://idm02.bw-cloud.org:5000/v3 + + os_identity_api_version: + type: string + default: '3' + + os_interface: + type: string + default: public + + os_application_credential_id: + type: string + default: 3f538f1823bd484e8238b2433de2f21a + + os_application_credential_secret: + type: string + + node_templates: + shop: + type: shop.component.ansible.os + properties: + application_name: unfurl-technology + DB_NAME: unfurl-technology + DB_USERNAME: root + DB_PASSWORD: {get_input: database_password} + DB_DIALECT: mysql + DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: database + - host: os_compute + + database: + type: mysql.database.ansible.mysql + properties: + database_name: unfurl-technology + requirements: + - host: mysql_dbms + + mysql_dbms: + type: mysql.dbms.ansible.os + properties: + root_password: {get_input: database_password} + requirements: + - host: os_compute + + os_compute: + type: os.compute.ansible.os + properties: + machine: unfurl-technology + ports: [80, 3000] + network: {get_input: os_network} + flavor: m1.large diff --git a/examples/unfurl-technology-automated-counting/tests/static-large/test.yaml b/examples/unfurl-technology-automated-counting/tests/static-large/test.yaml new file mode 100644 index 0000000000..ce9ef7de89 --- /dev/null +++ b/examples/unfurl-technology-automated-counting/tests/static-large/test.yaml @@ -0,0 +1 @@ +presets: static-large diff --git a/examples/unfurl-technology-automated-counting/tests/static/expected.yaml b/examples/unfurl-technology-automated-counting/tests/static/expected.yaml new file mode 100644 index 0000000000..ede7ed1f7a --- /dev/null +++ b/examples/unfurl-technology-automated-counting/tests/static/expected.yaml @@ -0,0 +1,90 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + os_network: + type: string + default: public-belwue + + os_ssh_key_name: + type: string + default: default + + os_ssh_user: + type: string + default: ubuntu + + os_ssh_key_file: + type: string + default: /home/stoetzms/.ssh/bw-cloud--default + + os_region_name: + type: string + default: Mannheim + + os_auth_type: + type: string + default: v3applicationcredential + + os_auth_url: + type: string + default: https://idm02.bw-cloud.org:5000/v3 + + os_identity_api_version: + type: string + default: '3' + + os_interface: + type: string + default: public + + os_application_credential_id: + type: string + default: 3f538f1823bd484e8238b2433de2f21a + + os_application_credential_secret: + type: string + + node_templates: + shop: + type: shop.component.ansible.os + properties: + application_name: unfurl-technology + DB_NAME: unfurl-technology + DB_USERNAME: root + DB_PASSWORD: {get_input: database_password} + DB_DIALECT: mysql + DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: database + - host: os_compute + + database: + type: mysql.database.ansible.mysql + properties: + database_name: unfurl-technology + requirements: + - host: mysql_dbms + + mysql_dbms: + type: mysql.dbms.ansible.os + properties: + root_password: {get_input: database_password} + requirements: + - host: os_compute + + os_compute: + type: os.compute.ansible.os + properties: + machine: unfurl-technology + ports: [80, 3000] + network: {get_input: os_network} + flavor: m1.medium diff --git a/examples/unfurl-technology-automated-counting/tests/static/test.yaml b/examples/unfurl-technology-automated-counting/tests/static/test.yaml new file mode 100644 index 0000000000..b263399f57 --- /dev/null +++ b/examples/unfurl-technology-automated-counting/tests/static/test.yaml @@ -0,0 +1 @@ +presets: static diff --git a/examples/unfurl-technology-automated-counting/variable-service-template.yaml b/examples/unfurl-technology-automated-counting/variable-service-template.yaml new file mode 100644 index 0000000000..a097f0269b --- /dev/null +++ b/examples/unfurl-technology-automated-counting/variable-service-template.yaml @@ -0,0 +1,194 @@ +tosca_definitions_version: tosca_variability_1_0 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + os_network: + type: string + default: public-belwue + conditions: {logic_expression: is_static} + + os_ssh_key_name: + type: string + default: default + conditions: {logic_expression: is_static} + + os_ssh_user: + type: string + default: ubuntu + conditions: {logic_expression: is_static} + + os_ssh_key_file: + type: string + default: /home/stoetzms/.ssh/bw-cloud--default + conditions: {logic_expression: is_static} + + os_region_name: + type: string + default: Mannheim + conditions: {logic_expression: is_static} + + os_auth_type: + type: string + default: v3applicationcredential + conditions: {logic_expression: is_static} + + os_auth_url: + type: string + default: https://idm02.bw-cloud.org:5000/v3 + conditions: {logic_expression: is_static} + + os_identity_api_version: + type: string + default: '3' + conditions: {logic_expression: is_static} + + os_interface: + type: string + default: public + conditions: {logic_expression: is_static} + + os_application_credential_id: + type: string + default: 3f538f1823bd484e8238b2433de2f21a + conditions: {logic_expression: is_static} + + os_application_credential_secret: + type: string + conditions: {logic_expression: is_static} + + gcp_region: + type: string + default: europe-west3 + conditions: {logic_expression: is_elastic} + + gcp_service_account_file: + type: string + default: /home/stoetzms/gcp/stoetzms-387808-2ec1cf865c76.json + conditions: {logic_expression: is_elastic} + + gcp_project: + type: string + default: stoetzms-387808 + conditions: {logic_expression: is_elastic} + + variability: + inputs: + env: + type: string + default: STATIC + + medium: + type: boolean + default: true + + presets: + static: + inputs: + env: STATIC + + static-large: + inputs: + env: STATIC + medium: false + + elastic: + inputs: + env: ELASTIC + + expressions: + is_static: {equal: [{variability_input: env}, STATIC]} + is_elastic: {equal: [{variability_input: env}, ELASTIC]} + + is_medium: {variability_input: medium} + is_large: {not: {logic_expression: is_medium}} + + options: + mode: semantic-loose + + node_default_condition_mode: incomingnaive-host + hosting_stack_constraint: true + + optimization_topology: true + optimization_topology_unique: true + + technology_pruning: true + technology_constraint: true + + optimization_technologies: min + optimization_technologies_mode: count + + node_templates: + shop: + type: shop.component + persistent: true + properties: + - application_name: unfurl-technology + - DB_NAME: unfurl-technology + - DB_USERNAME: root + - DB_PASSWORD: {get_input: database_password} + - DB_DIALECT: mysql + - DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + - DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: + node: database + + - host: + node: os_compute + conditions: {logic_expression: is_static} + + - host: + node: gcp_runtime + conditions: {logic_expression: is_elastic} + + database: + type: mysql.database + persistent: true + properties: + - database_name: unfurl-technology + requirements: + - host: + node: mysql_dbms + conditions: {logic_expression: is_static} + + - host: + node: gcp_dbms + conditions: {logic_expression: is_elastic} + + mysql_dbms: + type: mysql.dbms + properties: + - root_password: {get_input: database_password} + requirements: + - host: + node: os_compute + + os_compute: + type: os.compute + properties: + - machine: unfurl-technology + - ports: [80, 3000] + - network: {get_input: os_network} + - flavor: + value: m1.medium + conditions: {logic_expression: is_medium} + + - flavor: + value: m1.large + conditions: {logic_expression: is_large} + + gcp_dbms: + type: gcp.cloud_sql + properties: + - instance_name: unfurl-technology + - root_password: {get_input: database_password} + + gcp_runtime: + type: gcp.app_engine diff --git a/examples/unfurl-technology-automated-random/.gitignore b/examples/unfurl-technology-automated-random/.gitignore new file mode 100644 index 0000000000..4fe5ca855c --- /dev/null +++ b/examples/unfurl-technology-automated-random/.gitignore @@ -0,0 +1,2 @@ +files +lib diff --git a/examples/unfurl-technology-automated-random/config.yaml b/examples/unfurl-technology-automated-random/config.yaml new file mode 100644 index 0000000000..8b7a206366 --- /dev/null +++ b/examples/unfurl-technology-automated-random/config.yaml @@ -0,0 +1,3 @@ +dependencies: + - source: ../unfurl-technology-automated-weighted/lib + - source: ../unfurl-technology-automated-weighted/files diff --git a/examples/unfurl-technology-automated-random/stats.sh b/examples/unfurl-technology-automated-random/stats.sh new file mode 100644 index 0000000000..7cb56a56ac --- /dev/null +++ b/examples/unfurl-technology-automated-random/stats.sh @@ -0,0 +1,4 @@ +#!/usr/bin/bash +set -e + +yarn cli template stats --template ${PWD}/variable-service-template.yaml \ No newline at end of file diff --git a/examples/unfurl-technology-automated-random/tests/elastic/expected.yaml b/examples/unfurl-technology-automated-random/tests/elastic/expected.yaml new file mode 100644 index 0000000000..f6cfe08713 --- /dev/null +++ b/examples/unfurl-technology-automated-random/tests/elastic/expected.yaml @@ -0,0 +1,53 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + gcp_region: + type: string + default: europe-west3 + + gcp_service_account_file: + type: string + default: /home/stoetzms/gcp/stoetzms-387808-2ec1cf865c76.json + + gcp_project: + type: string + default: stoetzms-387808 + + node_templates: + shop: + type: shop.component.ansible.gcp + properties: + application_name: unfurl-technology + DB_NAME: unfurl-technology + DB_USERNAME: root + DB_PASSWORD: {get_input: database_password} + DB_DIALECT: mysql + DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: database + - host: gcp_runtime + + database: + type: mysql.database.ansible.gcp + properties: + database_name: unfurl-technology + requirements: + - host: gcp_dbms + + gcp_dbms: + type: gcp.cloud_sql.ansible.gcp + properties: + instance_name: unfurl-technology + root_password: {get_input: database_password} + + gcp_runtime: + type: gcp.app_engine.ansible.gcp diff --git a/examples/unfurl-technology-automated-random/tests/elastic/test.yaml b/examples/unfurl-technology-automated-random/tests/elastic/test.yaml new file mode 100644 index 0000000000..ce4eae556b --- /dev/null +++ b/examples/unfurl-technology-automated-random/tests/elastic/test.yaml @@ -0,0 +1 @@ +presets: elastic diff --git a/examples/unfurl-technology-automated-random/tests/static-large/expected.yaml b/examples/unfurl-technology-automated-random/tests/static-large/expected.yaml new file mode 100644 index 0000000000..292febc157 --- /dev/null +++ b/examples/unfurl-technology-automated-random/tests/static-large/expected.yaml @@ -0,0 +1,90 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + os_network: + type: string + default: public-belwue + + os_ssh_key_name: + type: string + default: default + + os_ssh_user: + type: string + default: ubuntu + + os_ssh_key_file: + type: string + default: /home/stoetzms/.ssh/bw-cloud--default + + os_region_name: + type: string + default: Mannheim + + os_auth_type: + type: string + default: v3applicationcredential + + os_auth_url: + type: string + default: https://idm02.bw-cloud.org:5000/v3 + + os_identity_api_version: + type: string + default: '3' + + os_interface: + type: string + default: public + + os_application_credential_id: + type: string + default: 3f538f1823bd484e8238b2433de2f21a + + os_application_credential_secret: + type: string + + node_templates: + shop: + type: shop.component.ansible.os + properties: + application_name: unfurl-technology + DB_NAME: unfurl-technology + DB_USERNAME: root + DB_PASSWORD: {get_input: database_password} + DB_DIALECT: mysql + DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: database + - host: os_compute + + database: + type: mysql.database.terraform.mysql + properties: + database_name: unfurl-technology + requirements: + - host: mysql_dbms + + mysql_dbms: + type: mysql.dbms.ansible.os + properties: + root_password: {get_input: database_password} + requirements: + - host: os_compute + + os_compute: + type: os.compute.ansible.os + properties: + machine: unfurl-technology + ports: [80, 3000] + network: {get_input: os_network} + flavor: m1.large diff --git a/examples/unfurl-technology-automated-random/tests/static-large/test.yaml b/examples/unfurl-technology-automated-random/tests/static-large/test.yaml new file mode 100644 index 0000000000..ce9ef7de89 --- /dev/null +++ b/examples/unfurl-technology-automated-random/tests/static-large/test.yaml @@ -0,0 +1 @@ +presets: static-large diff --git a/examples/unfurl-technology-automated-random/tests/static/expected.yaml b/examples/unfurl-technology-automated-random/tests/static/expected.yaml new file mode 100644 index 0000000000..5462be8b94 --- /dev/null +++ b/examples/unfurl-technology-automated-random/tests/static/expected.yaml @@ -0,0 +1,90 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + os_network: + type: string + default: public-belwue + + os_ssh_key_name: + type: string + default: default + + os_ssh_user: + type: string + default: ubuntu + + os_ssh_key_file: + type: string + default: /home/stoetzms/.ssh/bw-cloud--default + + os_region_name: + type: string + default: Mannheim + + os_auth_type: + type: string + default: v3applicationcredential + + os_auth_url: + type: string + default: https://idm02.bw-cloud.org:5000/v3 + + os_identity_api_version: + type: string + default: '3' + + os_interface: + type: string + default: public + + os_application_credential_id: + type: string + default: 3f538f1823bd484e8238b2433de2f21a + + os_application_credential_secret: + type: string + + node_templates: + shop: + type: shop.component.ansible.os + properties: + application_name: unfurl-technology + DB_NAME: unfurl-technology + DB_USERNAME: root + DB_PASSWORD: {get_input: database_password} + DB_DIALECT: mysql + DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: database + - host: os_compute + + database: + type: mysql.database.terraform.mysql + properties: + database_name: unfurl-technology + requirements: + - host: mysql_dbms + + mysql_dbms: + type: mysql.dbms.ansible.os + properties: + root_password: {get_input: database_password} + requirements: + - host: os_compute + + os_compute: + type: os.compute.ansible.os + properties: + machine: unfurl-technology + ports: [80, 3000] + network: {get_input: os_network} + flavor: m1.medium diff --git a/examples/unfurl-technology-automated-random/tests/static/test.yaml b/examples/unfurl-technology-automated-random/tests/static/test.yaml new file mode 100644 index 0000000000..b263399f57 --- /dev/null +++ b/examples/unfurl-technology-automated-random/tests/static/test.yaml @@ -0,0 +1 @@ +presets: static diff --git a/examples/unfurl-technology-automated-random/variable-service-template.yaml b/examples/unfurl-technology-automated-random/variable-service-template.yaml new file mode 100644 index 0000000000..9b1fc993f8 --- /dev/null +++ b/examples/unfurl-technology-automated-random/variable-service-template.yaml @@ -0,0 +1,191 @@ +tosca_definitions_version: tosca_variability_1_0 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + os_network: + type: string + default: public-belwue + conditions: {logic_expression: is_static} + + os_ssh_key_name: + type: string + default: default + conditions: {logic_expression: is_static} + + os_ssh_user: + type: string + default: ubuntu + conditions: {logic_expression: is_static} + + os_ssh_key_file: + type: string + default: /home/stoetzms/.ssh/bw-cloud--default + conditions: {logic_expression: is_static} + + os_region_name: + type: string + default: Mannheim + conditions: {logic_expression: is_static} + + os_auth_type: + type: string + default: v3applicationcredential + conditions: {logic_expression: is_static} + + os_auth_url: + type: string + default: https://idm02.bw-cloud.org:5000/v3 + conditions: {logic_expression: is_static} + + os_identity_api_version: + type: string + default: '3' + conditions: {logic_expression: is_static} + + os_interface: + type: string + default: public + conditions: {logic_expression: is_static} + + os_application_credential_id: + type: string + default: 3f538f1823bd484e8238b2433de2f21a + conditions: {logic_expression: is_static} + + os_application_credential_secret: + type: string + conditions: {logic_expression: is_static} + + gcp_region: + type: string + default: europe-west3 + conditions: {logic_expression: is_elastic} + + gcp_service_account_file: + type: string + default: /home/stoetzms/gcp/stoetzms-387808-2ec1cf865c76.json + conditions: {logic_expression: is_elastic} + + gcp_project: + type: string + default: stoetzms-387808 + conditions: {logic_expression: is_elastic} + + variability: + inputs: + env: + type: string + default: STATIC + + medium: + type: boolean + default: true + + presets: + static: + inputs: + env: STATIC + + static-large: + inputs: + env: STATIC + medium: false + + elastic: + inputs: + env: ELASTIC + + expressions: + is_static: {equal: [{variability_input: env}, STATIC]} + is_elastic: {equal: [{variability_input: env}, ELASTIC]} + + is_medium: {variability_input: medium} + is_large: {not: {logic_expression: is_medium}} + + options: + mode: semantic-loose + + node_default_condition_mode: incomingnaive-host + hosting_stack_constraint: true + + optimization_topology: true + optimization_topology_unique: true + + technology_pruning: true + technology_constraint: true + + node_templates: + shop: + type: shop.component + persistent: true + properties: + - application_name: unfurl-technology + - DB_NAME: unfurl-technology + - DB_USERNAME: root + - DB_PASSWORD: {get_input: database_password} + - DB_DIALECT: mysql + - DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + - DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: + node: database + + - host: + node: os_compute + conditions: {logic_expression: is_static} + + - host: + node: gcp_runtime + conditions: {logic_expression: is_elastic} + + database: + type: mysql.database + persistent: true + properties: + - database_name: unfurl-technology + requirements: + - host: + node: mysql_dbms + conditions: {logic_expression: is_static} + + - host: + node: gcp_dbms + conditions: {logic_expression: is_elastic} + + mysql_dbms: + type: mysql.dbms + properties: + - root_password: {get_input: database_password} + requirements: + - host: + node: os_compute + + os_compute: + type: os.compute + properties: + - machine: unfurl-technology + - ports: [80, 3000] + - network: {get_input: os_network} + - flavor: + value: m1.medium + conditions: {logic_expression: is_medium} + + - flavor: + value: m1.large + conditions: {logic_expression: is_large} + + gcp_dbms: + type: gcp.cloud_sql + properties: + - instance_name: unfurl-technology + - root_password: {get_input: database_password} + + gcp_runtime: + type: gcp.app_engine diff --git a/examples/unfurl-technology-automated-weighted/files/mysql.dbms.create.sh b/examples/unfurl-technology-automated-weighted/files/mysql.dbms.create.sh new file mode 100644 index 0000000000..d470166236 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/files/mysql.dbms.create.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env 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 diff --git a/examples/unfurl-technology-automated-weighted/files/shop.create.sh b/examples/unfurl-technology-automated-weighted/files/shop.create.sh new file mode 100644 index 0000000000..1547346370 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/files/shop.create.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +set -e + +APPLICATION_NAME="$1" +APPLICATION_ARTIFACT="$2" +APPLICATION_DIRECTORY="/var/lib/node-applications/${APPLICATION_NAME}" +APPLICATION_PORT="80" +APPLICATION_INTERFACE="0.0.0.0" + +DB_DIALECT="$3" +DB_NAME="$4" +DB_USERNAME="$5" +DB_PASSWORD="$6" +DB_ADDRESS="$7" +DB_PORT="$8" + +# Ensure artifact exists +if [ ! -f ${APPLICATION_ARTIFACT} ]; then + echo "Application artifact \"${APPLICATION_ARTIFACT}\" not found" + exit 1 +fi + +# Install Node.js +if [ ! -f /usr/bin/node ]; then + curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - &&\ + sudo apt-get install -y nodejs +fi + +# Create applications directory +mkdir -p /var/lib/node-applications + +# Create application directory +mkdir -p ${APPLICATION_DIRECTORY} + +# Extract deployment artifact in application directory +tar -xzf ${APPLICATION_ARTIFACT} -C ${APPLICATION_DIRECTORY} + +# Install dependencies +cd ${APPLICATION_DIRECTORY} +/usr/bin/npm ci + +# Create .env file +cat <> ${APPLICATION_DIRECTORY}/.env +PORT=${APPLICATION_PORT} +INTERFACE="${APPLICATION_INTERFACE}" +DB_DIALECT=${DB_DIALECT} +DB_NAME=${DB_NAME} +DB_USERNAME=${DB_USERNAME} +DB_PASSWORD=${DB_PASSWORD} +DB_ADDRESS=${DB_ADDRESS} +DB_PORT=${DB_PORT} +EOF + +# Create service +cat <> /etc/systemd/system/${APPLICATION_NAME}.service +[Unit] +After=network.target + +[Service] +Type=simple +ExecStart=/usr/bin/npm start +WorkingDirectory=${APPLICATION_DIRECTORY} +EnvironmentFile=${APPLICATION_DIRECTORY}/.env + +[Install] +WantedBy=multi-user.target +EOF + +# Start service +systemctl daemon-reload +systemctl start ${APPLICATION_NAME} +systemctl enable ${APPLICATION_NAME} diff --git a/examples/unfurl-technology-automated-weighted/files/shop.docker.tar.gz b/examples/unfurl-technology-automated-weighted/files/shop.docker.tar.gz new file mode 100644 index 0000000000..5fa28c3f68 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/files/shop.docker.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e089ffb732d30eb0ef1c9387da02619a1d5f18400d2f69e10fe3417b07919dd +size 73247415 diff --git a/examples/unfurl-technology-automated-weighted/files/shop.source.tar.gz b/examples/unfurl-technology-automated-weighted/files/shop.source.tar.gz new file mode 100644 index 0000000000..5f8c4c65cb --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/files/shop.source.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:448b13ebb5ecea5a8775acd03949dfb2a9f7903ab132baba553db3d9fe9b34bd +size 67797 diff --git a/examples/unfurl-technology-automated-weighted/files/shop.source.zip b/examples/unfurl-technology-automated-weighted/files/shop.source.zip new file mode 100644 index 0000000000..17c7b4060a --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/files/shop.source.zip @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:99530313f5475c8f02b2be19a34947c983988d8e817138762966156b2cd5d92f +size 68173 diff --git a/examples/unfurl-technology-automated-weighted/lib-loc.sh b/examples/unfurl-technology-automated-weighted/lib-loc.sh new file mode 100644 index 0000000000..a199ce7eeb --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/lib-loc.sh @@ -0,0 +1,4 @@ +#!/usr/bin/bash +set -e + +wc -l lib/* diff --git a/examples/unfurl-technology-automated-weighted/lib/gcp.app_engine.yaml b/examples/unfurl-technology-automated-weighted/lib/gcp.app_engine.yaml new file mode 100644 index 0000000000..beca227e8a --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/lib/gcp.app_engine.yaml @@ -0,0 +1,144 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +node_types: + ################################################### + # + # Abstract + # + ################################################### + + gcp.app_engine: + derived_from: tosca.nodes.Root + properties: + gcp_service_account_file: + type: string + default: {get_input: gcp_service_account_file} + + gcp_project: + type: string + default: {get_input: gcp_project} + + gcp_region: + type: string + default: {get_input: gcp_region} + + capabilities: + host: + type: tosca.capabilities.Compute + + requirements: + - host: + capability: tosca.capabilities.Compute + relationship: tosca.relationships.HostedOn + + ################################################### + # + # Ansible GCP + # + ################################################### + + gcp.app_engine.ansible.gcp: + derived_from: gcp.app_engine + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: Activate service account + shell: 'gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }}' + + # https://cloud.google.com/sql/docs/mysql/connect-instance-cloud-shell + - name: Enable Cloud Build API + shell: | + GCP_SERVICE=cloudbuild.googleapis.com + + GCP_SERVICE_ENABLED=$(gcloud services list --filter ${GCP_SERVICE} --format json --enabled | jq length) + if [ ${GCP_SERVICE_ENABLED} = 0 ]; then + gcloud services enable ${GCP_SERVICE} + fi + args: + executable: /usr/bin/bash + + - name: Enable appengine.googleapis.com + shell: | + GCP_SERVICE=appengine.googleapis.com + + GCP_SERVICE_ENABLED=$(gcloud services list --filter ${GCP_SERVICE} --format json --enabled | jq length) + if [ ${GCP_SERVICE_ENABLED} = 0 ]; then + gcloud services enable ${GCP_SERVICE} + fi + args: + executable: /usr/bin/bash + + # https://cloud.google.com/sdk/gcloud/reference/app/create + - name: Create GCP AppEngine + shell: 'gcloud app create --region {{ SELF.gcp_region }}' + register: app_create_command + failed_when: + - "'Created' not in app_create_command.stderr" + - "'already contains' not in app_create_command.stderr" + + ################################################### + # + # Terraform OS + # + ################################################### + + gcp.app_engine.terraform.gcp: + derived_from: gcp.app_engine + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + defaults: + inputs: + tfvars: | + project = "{{ SELF.gcp_project }}" + region = "{{ SELF.gcp_region }}" + credentials = "{{ SELF.gcp_service_account_file }}" + main: | + terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "4.67.0" + } + } + } + + provider "google" { + project = var.project + region = var.region + credentials = var.credentials + } + + variable "credentials" { + type = string + } + + variable "project" { + type = string + } + + variable "region" { + type = string + } + + resource "google_project_service" "app_engine_reporting" { + project = var.project + service = "appenginereporting.googleapis.com" + disable_on_destroy = false + } + + resource "google_project_service" "app_engine_admin" { + project = var.project + service = "appengine.googleapis.com" + disable_on_destroy = false + } diff --git a/examples/unfurl-technology-automated-weighted/lib/gcp.cloud_sql.yaml b/examples/unfurl-technology-automated-weighted/lib/gcp.cloud_sql.yaml new file mode 100644 index 0000000000..a38c114bf3 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/lib/gcp.cloud_sql.yaml @@ -0,0 +1,246 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +node_types: + ################################################### + # + # Abstract + # + ################################################### + + gcp.cloud_sql: + derived_from: tosca.nodes.Root + properties: + instance_name: + type: string + + root_password: + type: string + + gcp_service_account_file: + type: string + default: {get_input: gcp_service_account_file} + + gcp_project: + type: string + default: {get_input: gcp_project} + + gcp_region: + type: string + default: {get_input: gcp_region} + + attributes: + application_address: + type: string + + application_port: + type: integer + default: 3306 + + capabilities: + host: + type: tosca.capabilities.Compute + + requirements: + - host: + capability: tosca.capabilities.Compute + relationship: tosca.relationships.HostedOn + + ################################################### + # + # Terraform GCP + # + ################################################### + + gcp.cloud_sql.terraform.gcp: + derived_from: gcp.cloud_sql + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + application_address: application_address + inputs: + tfvars: | + project = "{{ SELF.gcp_project }}" + region = "{{ SELF.gcp_region }}" + service_account_file = "{{ SELF.gcp_service_account_file }}" + + name = "{{ SELF.instance_name}}" + password = "{{ SELF.root_password }}" + main: | + terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "4.67.0" + } + } + } + + provider "google" { + project = var.project + region = var.region + credentials = var.service_account_file + } + + variable "service_account_file" { + type = string + } + + variable "project" { + type = string + } + + variable "region" { + type = string + } + + variable "name" { + type = string + } + + variable "password" { + type = string + } + + resource "google_project_service" "cloud_sql_admin" { + project = var.project + service = "sqladmin.googleapis.com" + disable_on_destroy = false + } + + # https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database_instance + resource "google_sql_database_instance" "dbms" { + depends_on = [ google_project_service.cloud_sql_admin ] + + name = var.name + database_version = "MYSQL_5_7" + root_password = var.password + deletion_protection = false + + settings { + tier = "db-f1-micro" + + availability_type = "REGIONAL" + + backup_configuration { + enabled = true + binary_log_enabled = true + } + + ip_configuration { + ipv4_enabled = true + + authorized_networks { + name = "public" + value = "0.0.0.0/0" + } + + } + } + } + + resource "google_sql_user" "users" { + name = "root" + instance = google_sql_database_instance.dbms.name + host = "%" + password = var.password + } + + output "application_address" { + value = google_sql_database_instance.dbms.public_ip_address + } + + ################################################### + # + # Ansible GCP + # + ################################################### + + gcp.cloud_sql.ansible.gcp: + derived_from: gcp.cloud_sql + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: Activate service account + shell: gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }} + args: + executable: /usr/bin/bash + + # https://cloud.google.com/sql/docs/mysql/connect-instance-cloud-shell + - name: Enable Cloud SQL Admin API + shell: | + GCP_SERVICE=sqladmin.googleapis.com + + GCP_SERVICE_ENABLED=$(gcloud services list --filter ${GCP_SERVICE} --format json --enabled | jq length) + if [ ${GCP_SERVICE_ENABLED} = 0 ]; then + gcloud services enable ${GCP_SERVICE} + fi + args: + executable: /usr/bin/bash + + # https://cloud.google.com/sql/docs/mysql/create-instance + # https://cloud.google.com/sdk/gcloud/reference/sql/instances/create + - name: Create Instance + shell: | + gcloud sql instances create {{ SELF.instance_name }} \ + --tier db-f1-micro \ + --region {{ SELF.gcp_region }} \ + --database-version MYSQL_5_7 \ + --authorized-networks "0.0.0.0/0" \ + --availability-type REGIONAL \ + --backup --enable-bin-log \ + --timeout unlimited + args: + executable: /usr/bin/bash + + # https://cloud.google.com/sql/docs/mysql/create-instance + - name: Set Root Password + shell: gcloud sql users set-password root --host=% --instance {{ SELF.instance_name }} --password {{ SELF.root_password }} + args: + executable: /usr/bin/bash + + # https://cloud.google.com/sdk/gcloud/reference/sql/instances/describe + - name: Get Instance Information + shell: gcloud sql instances describe {{ SELF.instance_name }} + register: instance_info + args: + executable: /usr/bin/bash + + - name: Set Attributes + set_fact: + application_address: '{{ (instance_info.stdout | from_yaml).ipAddresses[0].ipAddress }}' + + resultTemplate: | + - name: SELF + attributes: + application_address: "{{ outputs.application_address | trim }}" + + outputs: + application_address: + + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: Activate service account + shell: 'gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }}' + + - name: Delete Instance + shell: 'gcloud sql instances delete {{ SELF.instance_name }} --quiet' diff --git a/examples/unfurl-technology-automated-weighted/lib/kubernetes.yaml b/examples/unfurl-technology-automated-weighted/lib/kubernetes.yaml new file mode 100644 index 0000000000..624401875a --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/lib/kubernetes.yaml @@ -0,0 +1,20 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +node_types: + kubernetes: + derived_from: unfurl.nodes.K8sCluster + + attributes: + api_server: + type: string + default: {concat: [{get_input: k8s_api_address}, ':', {get_input_k8s_api_port}]} + + capabilities: + endpoint: + type: unfurl.capabilities.Endpoint.K8sCluster + properties: + credential: + auth_type: api_key + cert_file: {get_input: k8s_ca_cert_file} + ca_cert: {get_input: k8s_client_cert_file} + key_file: {get_input: k8s_client_key_file} diff --git a/examples/unfurl-technology-automated-weighted/lib/mysql.database.yaml b/examples/unfurl-technology-automated-weighted/lib/mysql.database.yaml new file mode 100644 index 0000000000..69fa7944fe --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/lib/mysql.database.yaml @@ -0,0 +1,287 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +node_types: + ################################################### + # + # Abstract + # + ################################################### + + mysql.database: + derived_from: tosca.nodes.SoftwareComponent + + properties: + database_name: + type: string + + attributes: + management_address: + type: string + default: {eval: '.::.requirements[.name=host]::.target::management_address'} + + management_port: + type: integer + default: {eval: '.::.requirements[.name=host]::.target::management_port'} + + application_address: + type: string + default: {eval: '.::.requirements[.name=host]::.target::application_address'} + + application_port: + type: integer + 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 + + ################################################### + # + # Ansible Kubernetes + # + ################################################### + + # TODO: not required ... + mysql.database.ansible.kubernetes: + derived_from: mysql.database + + properties: + 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 + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + + - name: Create database + shell: kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql --host {{ HOST.management_address }} --port {{ HOST.management_port }} --password {{ HOST.root_password }} -e "create database {{ SELF.database_name }}"; + + playbookArgs: + - --key-file={{ SELF.os_ssh_key_file }} + - --user={{ SELF.os_ssh_user }} + - --ssh-common-args="-o IdentitiesOnly=yes -o BatchMode=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" + + ################################################### + # + # Ansible GCP + # + ################################################### + + mysql.database.ansible.gcp: + derived_from: mysql.database + + 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 + shell: 'gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }}' + + # https://cloud.google.com/sql/docs/mysql/create-manage-databases + - name: Create database + shell: 'gcloud sql databases create {{ SELF.database_name }} --instance {{ HOST.instance_name }}' + register: create_command + failed_when: + - "'Created database' not in create_command.stderr" + - "'database exists' not in create_command.stderr" + + ################################################### + # + # Terraform GCP + # + ################################################### + + mysql.database.terraform.gcp: + derived_from: mysql.database + + 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 + defaults: + inputs: + tfvars: | + project = "{{ SELF.gcp_project }}" + region = "{{ SELF.gcp_region }}" + credentials = "{{ SELF.gcp_service_account_file }}" + + name = "{{ SELF.database_name }}" + instance = "{{ HOST.instance_name }}" + main: | + terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "4.67.0" + } + } + } + + provider "google" { + project = var.project + region = var.region + credentials = var.credentials + } + + variable "credentials" { + type = string + } + + variable "project" { + type = string + } + + variable "region" { + type = string + } + + variable "name" { + type = string + } + + variable "instance" { + type = string + } + + resource "google_sql_database" "database" { + name = var.name + instance = var.instance + } + + ################################################### + # + # Terraform MySQL + # + ################################################### + + mysql.database.terraform.mysql: + derived_from: mysql.database + + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + defaults: + inputs: + tfvars: | + name = "{{ SELF.database_name }}" + root_password = "{{ HOST.root_password }}" + host = "{{ HOST.management_address }}" + port = {{ HOST.management_port }} + main: | + terraform { + required_providers { + mysql = { + source = "petoju/mysql" + version = "3.0.48" + } + } + } + + variable "name" { + type = string + } + + variable "host" { + type = string + } + + variable "root_password" { + type = string + } + + variable "port" { + type = number + } + + provider "mysql" { + endpoint = "${var.host}:${var.port}" + username = "root" + password = var.root_password + } + + resource "mysql_database" "app" { + name = var.name + } + + ################################################### + # + # Ansible MySQL + # + ################################################### + + mysql.database.ansible.mysql: + derived_from: mysql.database + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: Creating database + community.mysql.mysql_db: + name: '{{ SELF.database_name }}' + login_host: '{{ HOST.management_address }}' + login_password: '{{ HOST.root_password }}' + login_port: '{{ HOST.management_port }}' + login_user: root + state: present diff --git a/examples/unfurl-technology-automated-weighted/lib/mysql.dbms.yaml b/examples/unfurl-technology-automated-weighted/lib/mysql.dbms.yaml new file mode 100644 index 0000000000..e26af5b7a2 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/lib/mysql.dbms.yaml @@ -0,0 +1,459 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +node_types: + ################################################### + # + # Abstract + # + ################################################### + + mysql.dbms: + derived_from: tosca.nodes.Root + properties: + root_password: + type: string + + attributes: + management_address: + type: string + default: {eval: '.::.requirements[.name=host]::.target::management_address'} + + management_port: + type: integer + + application_address: + type: string + + application_port: + type: integer + + capabilities: + host: + type: tosca.capabilities.Compute + + requirements: + - host: + capability: tosca.capabilities.Compute + relationship: tosca.relationships.HostedOn + + ################################################### + # + # Ansible OS + # + ################################################### + + mysql.dbms.ansible.os: + derived_from: mysql.dbms + + properties: + 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: + management_port: + type: integer + default: 3000 + + application_address: + type: string + default: '127.0.0.1' + + application_port: + type: integer + default: 3000 + + capabilities: + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: + {eval: '.::..::.requirements[.name=host]::.target::.capabilities[.name=endpoint]::connection'} + host: {eval: '.::..::.requirements[.name=host]::.target::management_address'} + + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + inputs: + playbook: + q: + - name: Wait for ssh + wait_for_connection: + + - name: Installing mysql + package: + name: '{{item}}' + state: present + update_cache: yes + loop: + - mysql-server + - mysql-client + - python3-mysqldb + - libmysqlclient-dev + + - name: Start and enable mysql service + service: + name: mysql + state: started + enabled: yes + + - name: Create mysql user + community.mysql.mysql_user: + name: root + password: '{{ SELF.root_password }}' + priv: '*.*:ALL' + host: '%' + state: present + + - name: Delete localhost root + community.mysql.mysql_user: + name: root + host: localhost + state: absent + + - name: Enable passwordless login + copy: + dest: /root/.my.cnf + content: | + [client] + user=root + password={{ SELF.root_password }} + + - name: Enable remote login + lineinfile: + path: /etc/mysql/mysql.conf.d/mysqld.cnf + regexp: '^bind-address' + line: 'bind-address = 0.0.0.0' + backup: yes + + - name: Configure port (e.g., since 3306 is blocked by the provider) + lineinfile: + path: /etc/mysql/mysql.conf.d/mysqld.cnf + regexp: '^# port' + line: 'port = 3000' + backup: yes + + - name: Restart mysql + service: + name: mysql + state: restarted + + playbookArgs: + - --become + - --key-file={{ SELF.os_ssh_key_file }} + - --user={{ SELF.os_ssh_user }} + - --ssh-common-args="-o IdentitiesOnly=yes -o BatchMode=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" + + ################################################### + # + # Ansible Kubernetes + # + ################################################### + + # TODO: not required ... + mysql.dbms.ansible.kubernetes: + derived_from: tosca.nodes.Root + properties: + 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: + management_port: + type: integer + default: 3306 + + application_address: + type: string + default: mysql + + application_port: + type: integer + default: 3306 + + capabilities: + host: + type: tosca.capabilities.Compute + endpoint: + type: unfurl.capabilities.Endpoint.Ansible + properties: + connection: + {eval: '.::..::.requirements[.name=host]::.target::.capabilities[.name=endpoint]::connection'} + host: {eval: '.::..::.requirements[.name=host]::.target::management_address'} + + requirements: + - host: + capability: tosca.capabilities.Compute + relationship: tosca.relationships.HostedOn + + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + + - name: Create file + copy: + dest: mysql.yaml + content: | + --- + apiVersion: apps/v1 + kind: Deployment + metadata: + name: mysql + spec: + selector: + matchLabels: + app: mysql + strategy: + type: Recreate + template: + metadata: + labels: + app: mysql + spec: + containers: + - image: mysql:5.6 + name: mysql + env: + - name: MYSQL_ROOT_PASSWORD + value: {{ SELF.root_password }} + ports: + - containerPort: 3306 + name: mysql + + --- + apiVersion: v1 + kind: Service + metadata: + name: mysql + spec: + ports: + - port: 3306 + selector: + app: mysql + type: NodePort + + - name: Install MySQL DBMS + shell: | + kubectl apply -f mysql.yaml + kubectl rollout status deployment/mysql --timeout 60s + sleep 2m + + playbookArgs: + - --key-file={{ SELF.os_ssh_key_file }} + - --user={{ SELF.os_ssh_user }} + - --ssh-common-args="-o IdentitiesOnly=yes -o BatchMode=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" + + ################################################### + # + # Kubernetes Kubernetes + # + ################################################### + + # TODO: inherit from mysql.dbms? + mysql.dbms.kubernetes.kubernetes: + derived_from: unfurl.nodes.K8sRawResource + + attributes: + management_address: + type: string + default: {get_input: k8s_api_address} + + management_port: + type: integer + default: 30081 + + application_address: + type: string + default: mysql + + application_port: + type: integer + default: 3306 + + capabilities: + host: + type: tosca.capabilities.Compute + + requirements: + - host: + capability: tosca.capabilities.Compute + relationship: tosca.relationships.HostedOn + + properties: + root_password: + type: string + + definition: + type: any + default: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: mysql + namespace: default + spec: + selector: + matchLabels: + app: mysql + strategy: + type: Recreate + template: + metadata: + labels: + app: mysql + spec: + containers: + - image: mysql:5.6 + name: mysql + env: + - name: MYSQL_ROOT_PASSWORD + value: '{{ SELF.root_password }}' + ports: + - containerPort: '{{ SELF.application_port }}' + name: mysql + + mysql.dbms.expose.kubernetes.kubernetes: + derived_from: unfurl.nodes.K8sRawResource + properties: + definition: + type: any + default: + apiVersion: v1 + kind: Service + metadata: + name: mysql + namespace: default + spec: + ports: + - port: '{{ SELF.application_port }}' + nodePort: '{{ SELF.management_port }}' + selector: + app: mysql + type: NodePort + + ################################################### + # + # Terraform OS + # + ################################################### + + mysql.dbms.terraform.os: + derived_from: mysql.dbms + + properties: + 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'} + + artifact_script: + type: string + default: {eval: '.artifacts::artifact_script'} + + artifacts: + artifact_script: + type: tosca.artifacts.File + file: files/mysql.dbms.create.sh + + attributes: + management_port: + type: integer + default: 3000 + + application_address: + type: string + default: '127.0.0.1' + + application_port: + type: integer + default: 3000 + + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + defaults: + inputs: + tfvars: | + ssh_user = "{{ SELF.os_ssh_user }}" + ssh_key_file = "{{ SELF.os_ssh_key_file }}" + ssh_host = "{{ SELF.os_ssh_host }}" + + script = "{{ 'project' | get_dir }}/ensemble/{{ SELF.artifact_script.attributes.file }}" + password = "{{ SELF.root_password }}" + port = "{{ SELF.application_port }}" + main: | + variable "ssh_user" { + type = string + } + + variable "ssh_key_file" { + type = string + } + + variable "ssh_host" { + type = string + } + + variable "script" { + type = string + } + + variable "password" { + type = string + } + + variable "port" { + type = number + } + + resource "terraform_data" "os" { + + connection { + type = "ssh" + user = var.ssh_user + private_key = file(var.ssh_key_file) + host = var.ssh_host + } + + provisioner "file" { + source = var.script + destination = "/tmp/mysql.dbms.create.sh" + } + + provisioner "remote-exec" { + inline = [ + "sudo bash /tmp/mysql.dbms.create.sh ${var.password} ${var.port}", + ] + } + } diff --git a/examples/unfurl-technology-automated-weighted/lib/os.compute.yaml b/examples/unfurl-technology-automated-weighted/lib/os.compute.yaml new file mode 100644 index 0000000000..9af0c2b399 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/lib/os.compute.yaml @@ -0,0 +1,271 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +node_types: + ################################################### + # + # Abstract + # + ################################################### + + os.compute: + derived_from: tosca.nodes.Root + properties: + ports: + type: list + entry_schema: + type: integer + + machine: + type: string + + flavor: + type: string + default: 'm1.medium' + + network: + type: string + + 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} + + 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'} + + ################################################### + # + # Ansible OS + # + ################################################### + + os.compute.ansible.os: + derived_from: os.compute + + 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: Open ports + openstack.cloud.security_group_rule: + security_group: '{{ SELF.machine }}' + 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 }}' + image: 'Ubuntu 22.04' + key_name: 'default' + flavor: '{{ SELF.flavor }}' + network: '{{ SELF.network }}' + security_groups: "{{ 'default,' + SELF.machine }}" + auto_ip: false + register: server_info + + - name: Set attributes + set_fact: + management_address: '{{ server_info.server.accessIPv4 }}' + + resultTemplate: | + - name: SELF + attributes: + management_address: "{{ outputs.management_address | trim }}" + + # TODO: this is on the wrong level ... + outputs: + management_address: + + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: Delete VM + openstack.cloud.server: + state: absent + name: '{{ SELF.machine }}' + delete_fip: true + + - name: Delete security group + openstack.cloud.security_group: + state: absent + name: '{{ SELF.machine }}' + + ################################################### + # + # Terraform OS + # + ################################################### + + os.compute.terraform.os: + derived_from: os.compute + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + delete: + implementation: + primary: Terraform + defaults: + outputs: + management_address: management_address + inputs: + tfvars: | + os_region_name = "{{ SELF.os_region_name }}" + os_auth_url = "{{ SELF.os_auth_url }}" + + os_application_credential_id = "{{ SELF.os_application_credential_id }}" + os_application_credential_secret = "{{ SELF.os_application_credential_secret }}" + + ports = {{ SELF.ports | join("::") | split("::") | map("int") }} + machine = "{{ SELF.machine }}" + flavor = "{{ SELF.flavor }}" + network = "{{ SELF.network }}" + main: | + terraform { + required_version = ">= 0.14.0" + required_providers { + openstack = { + source = "terraform-provider-openstack/openstack" + version = "~> 1.48.0" + } + } + } + + provider "openstack" { + region = var.os_region_name + auth_url = var.os_auth_url + + application_credential_id = var.os_application_credential_id + application_credential_secret = var.os_application_credential_secret + } + + variable "os_region_name" { + type = string + } + + variable "os_auth_url" { + type = string + } + + variable "os_application_credential_id" { + type = string + } + + variable "os_application_credential_secret" { + type = string + } + + variable "ports" { + type = list(string) + } + + variable "machine" { + type = string + } + + variable "flavor" { + type = string + } + + variable "network" { + type = string + } + + resource "openstack_networking_secgroup_v2" "ports" { + name = var.machine + } + + resource "openstack_networking_secgroup_rule_v2" "port" { + for_each = toset(var.ports) + + direction = "ingress" + ethertype = "IPv4" + protocol = "tcp" + port_range_min = each.value + port_range_max = each.value + remote_ip_prefix = "0.0.0.0/0" + security_group_id = openstack_networking_secgroup_v2.ports.id + } + + resource "openstack_compute_instance_v2" "machine" { + name = var.machine + image_name = "Ubuntu 22.04" + flavor_name = var.flavor + key_pair = "default" + security_groups = ["default", openstack_networking_secgroup_v2.ports.name] + + network { + name = var.network + } + } + + output "management_address" { + value = yamldecode(openstack_compute_instance_v2.machine.access_ip_v4) + } diff --git a/examples/unfurl-technology-automated-weighted/lib/rules.yaml b/examples/unfurl-technology-automated-weighted/lib/rules.yaml new file mode 100644 index 0000000000..92a7dd86da --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/lib/rules.yaml @@ -0,0 +1,88 @@ +# TODO: drop "assign" + +ansible: + - component: shop.component + host: os.compute + weight: 1 + assign: shop.component.ansible.os + + - component: shop.component + host: gcp.app_engine + weight: 0.5 + assign: shop.component.ansible.gcp + + - component: os.compute + weight: 0.5 + assign: os.compute.ansible.os + + - component: gcp.app_engine + weight: 0.5 + assign: gcp.app_engine.ansible.gcp + + - component: gcp.cloud_sql + weight: 0.5 + assign: gcp.cloud_sql.ansible.gcp + + - component: mysql.database + host: gcp.cloud_sql + weight: 0.5 + assign: mysql.database.ansible.gcp + + - component: mysql.database + host: mysql.dbms + weight: 1 + assign: mysql.database.ansible.mysql + + - component: mysql.dbms + host: os.compute + weight: 1 + assign: mysql.dbms.ansible.os + +terraform: + - component: shop.component + host: os.compute + weight: 0 + assign: shop.component.terraform.os + + - component: shop.component + host: gcp.app_engine + weight: 1 + assign: shop.component.terraform.gcp + + - component: os.compute + weight: 1 + assign: os.compute.terraform.os + + - component: gcp.app_engine + weight: 1 + assign: gcp.app_engine.terraform.gcp + + - component: gcp.cloud_sql + weight: 1 + assign: gcp.cloud_sql.terraform.gcp + + - component: mysql.database + host: gcp.cloud_sql + weight: 1 + assign: mysql.database.terraform.gcp + + - component: mysql.database + host: mysql.dbms + weight: 0 + assign: mysql.database.terraform.mysql + + - component: mysql.dbms + host: os.compute + weight: 0 + assign: mysql.dbms.terraform.os + +kubernetes: + - component: shop.component + host: kubernetes + weight: 1 + assign: shop.component.kubernetes.kubernetes + + - component: mysql.dbms + host: kubernetes + weight: 1 + assign: mysql.dbms.kubernetes.kubernetes diff --git a/examples/unfurl-technology-automated-weighted/lib/shop.component.yaml b/examples/unfurl-technology-automated-weighted/lib/shop.component.yaml new file mode 100644 index 0000000000..e8f176631a --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/lib/shop.component.yaml @@ -0,0 +1,820 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +node_types: + ################################################### + # + # Abstract + # + ################################################### + + shop.component: + derived_from: tosca.nodes.SoftwareComponent + + properties: + application_name: + type: string + + DB_DIALECT: + type: string + + DB_NAME: + type: string + + DB_USERNAME: + type: string + + DB_PASSWORD: + type: string + + DB_ADDRESS: + type: string + + DB_PORT: + type: integer + + artifact_tar: + type: string + default: {eval: '.artifacts::artifact_tar '} + + artifact_zip: + type: string + default: {eval: '.artifacts::artifact_zip '} + + artifact_docker: + type: string + default: {eval: '.artifacts::artifact_docker '} + + artifacts: + artifact_tar: + type: tosca.artifacts.File + file: files/shop.source.tar.gz + + artifact_zip: + type: tosca.artifacts.File + file: files/shop.source.zip + + artifact_docker: + type: tosca.artifacts.File + file: files/shop.docker.tar.gz + + requirements: + - database: + capability: tosca.capabilities.Endpoint.Database + relationship: tosca.relationships.ConnectsTo + + ################################################### + # + # Ansible Kubernetes + # + ################################################### + + # TODO: not required ... + shop.component.ansible.kubernetes: + derived_from: shop.component + + properties: + 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 + inputs: + playbook: + q: + - name: wait for ssh + wait_for_connection: + + - name: Create application directory + file: + path: shop + state: directory + + - name: Copy deployment artifact + copy: + src: "{{ 'project' | get_dir }}/ensemble/{{ SELF.artifact_tar.attributes.file }}" + dest: shop + + - name: Extract deployment artifact + shell: | + cd shop + tar -xvf shop.tar.gz + + - name: Build Docker Image + shell: | + cd shop + eval $(minikube -p minikube docker-env) + docker build -t shop . + + - name: Create file + copy: + dest: shop.yaml + content: | + apiVersion: apps/v1 + kind: Deployment + metadata: + name: shop + spec: + selector: + matchLabels: + app: shop + template: + metadata: + labels: + app: shop + spec: + containers: + - image: shop + imagePullPolicy: Never + name: shop + env: + - name: DB_NAME + value: {{ SELF.DB_NAME }} + + - name: DB_PASSWORD + value: {{ SELF.DB_PASSWORD }} + + - name: DB_USERNAME + value: {{ SELF.DB_USERNAME }} + + - name: DB_ADDRESS + value: {{ SELF.DB_ADDRESS }} + + - name: DB_PORT + value: {{ SELF.DB_PORT }} + + - name: DB_DIALECT + value: {{ SELF.DB_DIALECT }} + + ports: + - containerPort: 80 + + --- + apiVersion: v1 + kind: Service + metadata: + name: shop + spec: + ports: + - port: 80 + selector: + app: shop + type: NodePort + + - name: Install shop component + shell: | + kubectl apply -f shop.yaml + kubectl rollout status deployment/shop --timeout 60s + + - name: create service + copy: + dest: '/etc/systemd/system/shop.service' + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=sudo -E kubectl port-forward service/shop 80:80 --address 0.0.0.0 + User=ubuntu + Group=ubuntu + + [Install] + WantedBy=multi-user.target + + - name: start service + systemd: + name: shop + state: started + enabled: yes + daemon_reload: yes + + playbookArgs: + - --become + - --key-file={{ SELF.ssh_key_file }} + - --user={{ SELF.ssh_user }} + - --ssh-common-args="-o IdentitiesOnly=yes -o BatchMode=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" + + ################################################### + # + # Kubernetes Kubernetes + # + ################################################### + + # TODO: inherit from shop.component? + shop.component.kubernetes.kubernetes: + derived_from: unfurl.nodes.K8sRawResource + + properties: + application_name: + type: string + + DB_DIALECT: + type: string + + DB_NAME: + type: string + + DB_USERNAME: + type: string + + DB_PASSWORD: + type: string + + DB_ADDRESS: + type: string + + DB_PORT: + type: integer + + definition: + type: any + default: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: shop + namespace: default + spec: + selector: + matchLabels: + app: shop + template: + metadata: + labels: + app: shop + spec: + containers: + - image: ghcr.io/opentosca/opentosca-shop-demo:latest + name: shop + env: + - name: DB_NAME + value: '{{ SELF.DB_NAME }}' + + - name: DB_PASSWORD + value: '{{ SELF.DB_PASSWORD }}' + + - name: DB_USERNAME + value: '{{ SELF.DB_USERNAME }}' + + - name: DB_ADDRESS + value: '{{ SELF.DB_ADDRESS }}' + + - name: DB_PORT + value: "'{{ SELF.DB_PORT }}'" + + - name: DB_DIALECT + value: '{{ SELF.DB_DIALECT }}' + + ports: + - containerPort: 80 + + requirements: + - database: + capability: tosca.capabilities.Endpoint.Database + relationship: tosca.relationships.ConnectsTo + + shop.component.expose.kubernetes.kubernetes: + derived_from: unfurl.nodes.K8sRawResource + properties: + definition: + type: any + default: + apiVersion: v1 + kind: Service + metadata: + name: shop + namespace: default + spec: + ports: + - port: 80 + nodePort: 30080 + selector: + app: shop + type: NodePort + + ################################################### + # + # Ansible OS + # + ################################################### + + shop.component.ansible.os: + derived_from: shop.component + + properties: + 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/node-applications/', {get_property: [SELF, application_name]}]} + + interfaces: + Standard: + operations: + create: + implementation: + primary: Ansible + operation_host: HOST + inputs: + playbook: + q: + - name: Wait for ssh + wait_for_connection: + + - name: Install Node.js + shell: | + if [ ! -f /usr/bin/node ]; then + curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - &&\ + sudo apt-get install -y nodejs + fi + args: + executable: /usr/bin/bash + + - name: Create applications directory + file: + path: /var/lib/node-applications/ + state: directory + + - name: Create application directory + file: + path: '{{ SELF.application_directory }}' + state: directory + + - name: Extract deployment artifact in application directory + unarchive: + src: "{{ 'project' | get_dir }}/ensemble/{{ SELF.artifact_tar.attributes.file }}" + dest: '{{ SELF.application_directory }}' + + - name: Install dependencies + shell: /usr/bin/npm ci + args: + chdir: '{{ SELF.application_directory }}' + + - name: Create .env file + copy: + dest: '{{ SELF.application_directory }}/.env' + content: | + PORT=80 + INTERFACE="0.0.0.0" + 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 | first }} + DB_PORT={{ SELF.DB_PORT }} + + - name: Create service + copy: + dest: '/etc/systemd/system/{{ SELF.application_name }}.service' + content: | + [Unit] + After=network.target + + [Service] + Type=simple + ExecStart=/usr/bin/npm start + WorkingDirectory={{ SELF.application_directory }} + EnvironmentFile={{ SELF.application_directory }}/.env + + [Install] + WantedBy=multi-user.target + + - name: Start service + 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 }} + - --ssh-common-args="-o IdentitiesOnly=yes -o BatchMode=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" + + delete: + implementation: + primary: Ansible + operation_host: HOST + inputs: + playbook: + q: + - name: Wait for ssh + wait_for_connection: + + - name: Stop service + systemd: + name: '{{ SELF.application_name }}' + state: stopped + + - name: Delete systemd service + file: + path: '/etc/systemd/system/{{ SELF.application_name }}.service' + state: absent + + - name: Reload daemon + systemd: + daemon_reload: true + + - name: Delete application directory + file: + path: '{{ SELF.application_directory }}' + state: absent + + playbookArgs: + - --become + - --key-file={{ SELF.os_ssh_key_file }} + - --user={{ SELF.os_ssh_user }} + - --ssh-common-args="-o IdentitiesOnly=yes -o BatchMode=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" + + ################################################### + # + # Ansible GCP + # + ################################################### + + shop.component.ansible.gcp: + derived_from: shop.component + + 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 + shell: 'gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }}' + + - name: Create working directory + tempfile: + state: directory + register: tempdir_info + + - name: Extract deployment artifact in working directory + unarchive: + src: "{{ 'project' | get_dir }}/ensemble/{{ SELF.artifact_tar.attributes.file }}" + dest: '{{ tempdir_info.path }}' + + # https://cloud.google.com/appengine/docs/standard/reference/app-yaml?tab=node.js + - name: Configure app yaml + copy: + dest: '{{ tempdir_info.path }}/app.yaml' + content: | + runtime: nodejs18 + service: {{ SELF.application_name }} + instance_class: F1 + env_variables: + 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 }} + + # https://cloud.google.com/sdk/gcloud/reference/app/deploy + - name: Create App + shell: 'gcloud app deploy {{ tempdir_info.path }} --quiet' + + delete: + implementation: + primary: Ansible + operation_host: ORCHESTRATOR + inputs: + playbook: + q: + - name: Activate service account + shell: 'gcloud auth activate-service-account --key-file {{ SELF.gcp_service_account_file }} --project {{ SELF.gcp_project }}' + + # https://cloud.google.com/sdk/gcloud/reference/app/deploy + - name: Create App + shell: 'gcloud app services delete {{ SELF.application_name }} --quiet' + + ################################################### + # + # Terraform GCP + # + ################################################### + + shop.component.terraform.gcp: + derived_from: shop.component + + 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: + tfvars: | + project = "{{ SELF.gcp_project }}" + region = "{{ SELF.gcp_region }}" + credentials = "{{ SELF.gcp_service_account_file }}" + + 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 }}" + + application_name = "{{ SELF.application_name }}" + artifact = "{{ 'project' | get_dir }}/ensemble/{{ SELF.artifact_zip.attributes.file }}" + main: | + terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "4.67.0" + } + } + } + + provider "google" { + project = var.project + region = var.region + credentials = var.credentials + } + + variable "credentials" { + type = string + } + + variable "project" { + type = string + } + + variable "region" { + type = string + } + + variable "artifact" { + type = string + } + + variable "application_name" { + type = string + } + + variable "db_dialect" { + type = string + } + + variable "db_name" { + type = string + } + + variable "db_username" { + type = string + } + + variable "db_password" { + type = string + } + + variable "db_address" { + type = string + } + + variable "db_port" { + type = number + } + + variable "try" { + type = string + default = "8" + } + + resource "google_app_engine_standard_app_version" "app" { + version_id = "v2" + service = var.application_name + runtime = "nodejs18" + app_engine_apis = true + + entrypoint { + shell = "node ./index.js" + } + + deployment { + zip { + source_url = "https://storage.googleapis.com/${google_storage_bucket.bucket.name}/${google_storage_bucket_object.object.name}" + } + } + + env_variables = { + DB_DIALECT = var.db_dialect + DB_NAME = var.db_name + DB_USERNAME = var.db_username + DB_PASSWORD = var.db_password + DB_ADDRESS = var.db_address + DB_PORT = var.db_port + } + + service_account = google_service_account.custom_service_account.email + } + + resource "google_storage_bucket" "bucket" { + name = "${var.project}-appengine-static-content-${var.try}" + location = "EU" + } + + resource "google_storage_bucket_object" "object" { + name = "object-${var.try}.zip" + bucket = google_storage_bucket.bucket.name + source = var.artifact + } + + resource "google_service_account" "custom_service_account" { + account_id = "${var.application_name}-account-${var.try}" + display_name = "Custom Service Account" + } + + resource "google_project_iam_member" "gae_api" { + project = google_service_account.custom_service_account.project + role = "roles/compute.networkUser" + member = "serviceAccount:${google_service_account.custom_service_account.email}" + } + + resource "google_project_iam_member" "storage_viewer" { + project = google_service_account.custom_service_account.project + role = "roles/storage.objectViewer" + member = "serviceAccount:${google_service_account.custom_service_account.email}" + } + + ################################################### + # + # Terraform OS + # + ################################################### + + shop.component.terraform.os: + derived_from: shop.component + + properties: + 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'} + + artifact_script: + type: string + default: {eval: '.artifacts::artifact_script'} + + artifacts: + artifact_script: + type: tosca.artifacts.File + file: files/shop.create.sh + + interfaces: + Standard: + operations: + configure: + implementation: + primary: Terraform + defaults: + inputs: + tfvars: | + ssh_user = "{{ SELF.os_ssh_user }}" + ssh_key_file = "{{ SELF.os_ssh_key_file }}" + ssh_host = "{{ SELF.os_ssh_host | frist }}" + + application_name = "{{ SELF.application_name }}" + application_artifact = "{{ 'project' | get_dir }}/ensemble/{{ SELF.artifact_tar.attributes.file }}" + application_script = "{{ 'project' | get_dir }}/ensemble/{{ SELF.artifact_script.attributes.file }}" + + 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 | first }}" + db_port="{{ SELF.DB_PORT }}" + main: | + variable "ssh_user" { + type = string + } + + variable "ssh_key_file" { + type = string + } + + variable "ssh_host" { + type = string + } + + variable "application_name" { + type = string + } + + variable "application_script" { + type = string + } + + variable "application_artifact" { + type = string + } + + variable "db_dialect" { + type = string + } + + variable "db_name" { + type = string + } + + variable "db_username" { + type = string + } + + variable "db_password" { + type = string + } + + variable "db_address" { + type = string + } + + variable "db_port" { + type = number + } + + resource "terraform_data" "os" { + + connection { + type = "ssh" + user = var.ssh_user + private_key = file(var.ssh_key_file) + host = var.ssh_host + } + + provisioner "file" { + source = var.application_artifact + destination = "/tmp/shop.tar.gz" + } + + provisioner "file" { + source = var.application_script + destination = "/tmp/shop.create.sh" + } + + provisioner "remote-exec" { + inline = [ + "sudo bash /tmp/shop.create.sh ${var.application_name} /tmp/shop.tar.gz ${var.db_dialect} ${var.db_name} ${var.db_username} ${var.db_password} ${var.db_address} ${var.db_port}", + ] + } + } diff --git a/examples/unfurl-technology-automated-weighted/lib/types.yaml b/examples/unfurl-technology-automated-weighted/lib/types.yaml new file mode 100644 index 0000000000..160cb54c12 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/lib/types.yaml @@ -0,0 +1,16 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - gcp.app_engine.yaml + - gcp.cloud_sql.yaml + - kubernetes.yaml + - mysql.database.yaml + - mysql.dbms.yaml + - os.compute.yaml + - shop.component.yaml + + - repository: unfurl + file: tosca_plugins/artifacts.yaml + + - repository: unfurl + file: tosca_plugins/k8s.yaml diff --git a/examples/unfurl-technology-automated-weighted/scripts/clean.sh b/examples/unfurl-technology-automated-weighted/scripts/clean.sh new file mode 100755 index 0000000000..3e56da8c94 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/scripts/clean.sh @@ -0,0 +1,7 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +$VINTNER setup clean --force diff --git a/examples/unfurl-technology-automated-weighted/scripts/code.sh b/examples/unfurl-technology-automated-weighted/scripts/code.sh new file mode 100755 index 0000000000..e7f3b3d5d4 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/scripts/code.sh @@ -0,0 +1,7 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +$VINTNER instances code --instance ${TEMPLATE_NAME} \ No newline at end of file diff --git a/examples/unfurl-technology-automated-weighted/scripts/configuration.env b/examples/unfurl-technology-automated-weighted/scripts/configuration.env new file mode 100644 index 0000000000..7e6bc536c3 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/scripts/configuration.env @@ -0,0 +1,4 @@ +TEMPLATE_NAME="technology-weighted" +#VINTNER="node ../../../build/cli/index.js" +VINTNER="yarn cli" +DEPLOYMENT_VARIANT="elastic" \ No newline at end of file diff --git a/examples/unfurl-technology-automated-weighted/scripts/configuration.sh b/examples/unfurl-technology-automated-weighted/scripts/configuration.sh new file mode 100755 index 0000000000..5e4da0d86a --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/scripts/configuration.sh @@ -0,0 +1,29 @@ +#! /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 DEPLOYMENT_VARIANT is defined +if [[ -z ${DEPLOYMENT_VARIANT} ]]; then + echo "DEPLOYMENT_VARIANT is not defined" + exit 1 +fi + +# Set template directory +TEMPLATE_DIR=$(readlink -f $(dirname $0)/../) diff --git a/examples/unfurl-technology-automated-weighted/scripts/continue.sh b/examples/unfurl-technology-automated-weighted/scripts/continue.sh new file mode 100755 index 0000000000..d28f5b2efe --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/scripts/continue.sh @@ -0,0 +1,7 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +$VINTNER instances continue --instance ${TEMPLATE_NAME} diff --git a/examples/unfurl-technology-automated-weighted/scripts/deploy.sh b/examples/unfurl-technology-automated-weighted/scripts/deploy.sh new file mode 100755 index 0000000000..3158779670 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/scripts/deploy.sh @@ -0,0 +1,11 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +$VINTNER templates import --template ${TEMPLATE_NAME} --path ${TEMPLATE_DIR} +$VINTNER instances init --instance ${TEMPLATE_NAME} --template ${TEMPLATE_NAME} +$VINTNER instances resolve --instance ${TEMPLATE_NAME} --presets ${DEPLOYMENT_VARIANT} +$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-automated-weighted/scripts/quality.sh b/examples/unfurl-technology-automated-weighted/scripts/quality.sh new file mode 100644 index 0000000000..f6ec287d7c --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/scripts/quality.sh @@ -0,0 +1,8 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +# Quality +$VINTNER template quality --template ${TEMPLATE_DIR}/variable-service-template.yaml --presets ${DEPLOYMENT_VARIANT} \ No newline at end of file diff --git a/examples/unfurl-technology-automated-weighted/scripts/reimport.sh b/examples/unfurl-technology-automated-weighted/scripts/reimport.sh new file mode 100755 index 0000000000..2b0047fdd5 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/scripts/reimport.sh @@ -0,0 +1,15 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +$VINTNER instances delete --instance ${TEMPLATE_NAME} + +$VINTNER templates delete --template ${TEMPLATE_NAME} + +$VINTNER templates import --template ${TEMPLATE_NAME} --path ${TEMPLATE_DIR} +$VINTNER instances init --instance ${TEMPLATE_NAME} --template ${TEMPLATE_NAME} +$VINTNER instances resolve --instance ${TEMPLATE_NAME} --presets ${DEPLOYMENT_VARIANT} +$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-automated-weighted/scripts/setup.sh b/examples/unfurl-technology-automated-weighted/scripts/setup.sh new file mode 100755 index 0000000000..e7b7e0cb4f --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/scripts/setup.sh @@ -0,0 +1,10 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +$VINTNER setup init +$VINTNER orchestrators init unfurl +$VINTNER orchestrators enable --orchestrator unfurl +$VINTNER orchestrators attest --orchestrator unfurl \ No newline at end of file diff --git a/examples/unfurl-technology-automated-weighted/scripts/undeploy.sh b/examples/unfurl-technology-automated-weighted/scripts/undeploy.sh new file mode 100755 index 0000000000..6b6e374f69 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/scripts/undeploy.sh @@ -0,0 +1,7 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +$VINTNER instances undeploy --instance ${TEMPLATE_NAME} diff --git a/examples/unfurl-technology-automated-weighted/stats.sh b/examples/unfurl-technology-automated-weighted/stats.sh new file mode 100644 index 0000000000..7cb56a56ac --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/stats.sh @@ -0,0 +1,4 @@ +#!/usr/bin/bash +set -e + +yarn cli template stats --template ${PWD}/variable-service-template.yaml \ No newline at end of file diff --git a/examples/unfurl-technology-automated-weighted/tests/elastic/test.yaml b/examples/unfurl-technology-automated-weighted/tests/elastic/test.yaml new file mode 100644 index 0000000000..ea8db06698 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/tests/elastic/test.yaml @@ -0,0 +1,2 @@ +expected: ../../../unfurl-technology-baseline-elastic/variable-service-template.yaml +presets: elastic diff --git a/examples/unfurl-technology-automated-weighted/tests/static-large/test.yaml b/examples/unfurl-technology-automated-weighted/tests/static-large/test.yaml new file mode 100644 index 0000000000..4b3ef3f31d --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/tests/static-large/test.yaml @@ -0,0 +1,2 @@ +expected: ../../../unfurl-technology-baseline-static-large/variable-service-template.yaml +presets: static-large diff --git a/examples/unfurl-technology-automated-weighted/tests/static/test.yaml b/examples/unfurl-technology-automated-weighted/tests/static/test.yaml new file mode 100644 index 0000000000..58d9cdacfa --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/tests/static/test.yaml @@ -0,0 +1,2 @@ +expected: ../../../unfurl-technology-baseline-static/variable-service-template.yaml +presets: static diff --git a/examples/unfurl-technology-automated-weighted/variable-service-template.yaml b/examples/unfurl-technology-automated-weighted/variable-service-template.yaml new file mode 100644 index 0000000000..36b6c31114 --- /dev/null +++ b/examples/unfurl-technology-automated-weighted/variable-service-template.yaml @@ -0,0 +1,194 @@ +tosca_definitions_version: tosca_variability_1_0 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + os_network: + type: string + default: public-belwue + conditions: {logic_expression: is_static} + + os_ssh_key_name: + type: string + default: default + conditions: {logic_expression: is_static} + + os_ssh_user: + type: string + default: ubuntu + conditions: {logic_expression: is_static} + + os_ssh_key_file: + type: string + default: /home/stoetzms/.ssh/bw-cloud--default + conditions: {logic_expression: is_static} + + os_region_name: + type: string + default: Mannheim + conditions: {logic_expression: is_static} + + os_auth_type: + type: string + default: v3applicationcredential + conditions: {logic_expression: is_static} + + os_auth_url: + type: string + default: https://idm02.bw-cloud.org:5000/v3 + conditions: {logic_expression: is_static} + + os_identity_api_version: + type: string + default: '3' + conditions: {logic_expression: is_static} + + os_interface: + type: string + default: public + conditions: {logic_expression: is_static} + + os_application_credential_id: + type: string + default: 3f538f1823bd484e8238b2433de2f21a + conditions: {logic_expression: is_static} + + os_application_credential_secret: + type: string + conditions: {logic_expression: is_static} + + gcp_region: + type: string + default: europe-west3 + conditions: {logic_expression: is_elastic} + + gcp_service_account_file: + type: string + default: /home/stoetzms/gcp/stoetzms-387808-2ec1cf865c76.json + conditions: {logic_expression: is_elastic} + + gcp_project: + type: string + default: stoetzms-387808 + conditions: {logic_expression: is_elastic} + + variability: + inputs: + env: + type: string + default: STATIC + + medium: + type: boolean + default: true + + presets: + static: + inputs: + env: STATIC + + static-large: + inputs: + env: STATIC + medium: false + + elastic: + inputs: + env: ELASTIC + + expressions: + is_static: {equal: [{variability_input: env}, STATIC]} + is_elastic: {equal: [{variability_input: env}, ELASTIC]} + + is_medium: {variability_input: medium} + is_large: {not: {logic_expression: is_medium}} + + options: + mode: semantic-loose + + node_default_condition_mode: incomingnaive-host + hosting_stack_constraint: true + + optimization_topology: true + optimization_topology_unique: true + + technology_pruning: true + technology_constraint: true + + optimization_technologies: max + optimization_technologies_mode: weight + + node_templates: + shop: + type: shop.component + persistent: true + properties: + - application_name: unfurl-technology + - DB_NAME: unfurl-technology + - DB_USERNAME: root + - DB_PASSWORD: {get_input: database_password} + - DB_DIALECT: mysql + - DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + - DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: + node: database + + - host: + node: os_compute + conditions: {logic_expression: is_static} + + - host: + node: gcp_runtime + conditions: {logic_expression: is_elastic} + + database: + type: mysql.database + persistent: true + properties: + - database_name: unfurl-technology + requirements: + - host: + node: mysql_dbms + conditions: {logic_expression: is_static} + + - host: + node: gcp_dbms + conditions: {logic_expression: is_elastic} + + mysql_dbms: + type: mysql.dbms + properties: + - root_password: {get_input: database_password} + requirements: + - host: + node: os_compute + + os_compute: + type: os.compute + properties: + - machine: unfurl-technology + - ports: [80, 3000] + - network: {get_input: os_network} + - flavor: + value: m1.medium + conditions: {logic_expression: is_medium} + + - flavor: + value: m1.large + conditions: {logic_expression: is_large} + + gcp_dbms: + type: gcp.cloud_sql + properties: + - instance_name: unfurl-technology + - root_password: {get_input: database_password} + + gcp_runtime: + type: gcp.app_engine diff --git a/examples/unfurl-technology-baseline-elastic/.gitignore b/examples/unfurl-technology-baseline-elastic/.gitignore new file mode 100644 index 0000000000..4fe5ca855c --- /dev/null +++ b/examples/unfurl-technology-baseline-elastic/.gitignore @@ -0,0 +1,2 @@ +files +lib diff --git a/examples/unfurl-technology-baseline-elastic/config.yaml b/examples/unfurl-technology-baseline-elastic/config.yaml new file mode 100644 index 0000000000..8b7a206366 --- /dev/null +++ b/examples/unfurl-technology-baseline-elastic/config.yaml @@ -0,0 +1,3 @@ +dependencies: + - source: ../unfurl-technology-automated-weighted/lib + - source: ../unfurl-technology-automated-weighted/files diff --git a/examples/unfurl-technology-baseline-elastic/scripts/clean.sh b/examples/unfurl-technology-baseline-elastic/scripts/clean.sh new file mode 100644 index 0000000000..3e56da8c94 --- /dev/null +++ b/examples/unfurl-technology-baseline-elastic/scripts/clean.sh @@ -0,0 +1,7 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +$VINTNER setup clean --force diff --git a/examples/unfurl-technology-baseline-elastic/scripts/code.sh b/examples/unfurl-technology-baseline-elastic/scripts/code.sh new file mode 100644 index 0000000000..e7f3b3d5d4 --- /dev/null +++ b/examples/unfurl-technology-baseline-elastic/scripts/code.sh @@ -0,0 +1,7 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +$VINTNER instances code --instance ${TEMPLATE_NAME} \ No newline at end of file diff --git a/examples/unfurl-technology-baseline-elastic/scripts/configuration.env b/examples/unfurl-technology-baseline-elastic/scripts/configuration.env new file mode 100644 index 0000000000..4e8d5615d9 --- /dev/null +++ b/examples/unfurl-technology-baseline-elastic/scripts/configuration.env @@ -0,0 +1,4 @@ +TEMPLATE_NAME="technology-baseline-elastic" +#VINTNER="node ../../../build/cli/index.js" +VINTNER="yarn cli" +DEPLOYMENT_VARIANT="elastic" \ No newline at end of file diff --git a/examples/unfurl-technology-baseline-elastic/scripts/configuration.sh b/examples/unfurl-technology-baseline-elastic/scripts/configuration.sh new file mode 100644 index 0000000000..5e4da0d86a --- /dev/null +++ b/examples/unfurl-technology-baseline-elastic/scripts/configuration.sh @@ -0,0 +1,29 @@ +#! /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 DEPLOYMENT_VARIANT is defined +if [[ -z ${DEPLOYMENT_VARIANT} ]]; then + echo "DEPLOYMENT_VARIANT is not defined" + exit 1 +fi + +# Set template directory +TEMPLATE_DIR=$(readlink -f $(dirname $0)/../) diff --git a/examples/unfurl-technology-baseline-elastic/scripts/continue.sh b/examples/unfurl-technology-baseline-elastic/scripts/continue.sh new file mode 100644 index 0000000000..d28f5b2efe --- /dev/null +++ b/examples/unfurl-technology-baseline-elastic/scripts/continue.sh @@ -0,0 +1,7 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +$VINTNER instances continue --instance ${TEMPLATE_NAME} diff --git a/examples/unfurl-technology-baseline-elastic/scripts/deploy.sh b/examples/unfurl-technology-baseline-elastic/scripts/deploy.sh new file mode 100644 index 0000000000..3158779670 --- /dev/null +++ b/examples/unfurl-technology-baseline-elastic/scripts/deploy.sh @@ -0,0 +1,11 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +$VINTNER templates import --template ${TEMPLATE_NAME} --path ${TEMPLATE_DIR} +$VINTNER instances init --instance ${TEMPLATE_NAME} --template ${TEMPLATE_NAME} +$VINTNER instances resolve --instance ${TEMPLATE_NAME} --presets ${DEPLOYMENT_VARIANT} +$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-baseline-elastic/scripts/quality.sh b/examples/unfurl-technology-baseline-elastic/scripts/quality.sh new file mode 100644 index 0000000000..aab83cf22c --- /dev/null +++ b/examples/unfurl-technology-baseline-elastic/scripts/quality.sh @@ -0,0 +1,8 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +# Quality +$VINTNER template quality --template ${TEMPLATE_DIR}/variable-service-template.yaml \ No newline at end of file diff --git a/examples/unfurl-technology-baseline-elastic/scripts/reimport.sh b/examples/unfurl-technology-baseline-elastic/scripts/reimport.sh new file mode 100644 index 0000000000..2b0047fdd5 --- /dev/null +++ b/examples/unfurl-technology-baseline-elastic/scripts/reimport.sh @@ -0,0 +1,15 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +$VINTNER instances delete --instance ${TEMPLATE_NAME} + +$VINTNER templates delete --template ${TEMPLATE_NAME} + +$VINTNER templates import --template ${TEMPLATE_NAME} --path ${TEMPLATE_DIR} +$VINTNER instances init --instance ${TEMPLATE_NAME} --template ${TEMPLATE_NAME} +$VINTNER instances resolve --instance ${TEMPLATE_NAME} --presets ${DEPLOYMENT_VARIANT} +$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-baseline-elastic/scripts/setup.sh b/examples/unfurl-technology-baseline-elastic/scripts/setup.sh new file mode 100644 index 0000000000..e7b7e0cb4f --- /dev/null +++ b/examples/unfurl-technology-baseline-elastic/scripts/setup.sh @@ -0,0 +1,10 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +$VINTNER setup init +$VINTNER orchestrators init unfurl +$VINTNER orchestrators enable --orchestrator unfurl +$VINTNER orchestrators attest --orchestrator unfurl \ No newline at end of file diff --git a/examples/unfurl-technology-baseline-elastic/scripts/undeploy.sh b/examples/unfurl-technology-baseline-elastic/scripts/undeploy.sh new file mode 100644 index 0000000000..6b6e374f69 --- /dev/null +++ b/examples/unfurl-technology-baseline-elastic/scripts/undeploy.sh @@ -0,0 +1,7 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +$VINTNER instances undeploy --instance ${TEMPLATE_NAME} diff --git a/examples/unfurl-technology-baseline-elastic/stats.sh b/examples/unfurl-technology-baseline-elastic/stats.sh new file mode 100644 index 0000000000..7cb56a56ac --- /dev/null +++ b/examples/unfurl-technology-baseline-elastic/stats.sh @@ -0,0 +1,4 @@ +#!/usr/bin/bash +set -e + +yarn cli template stats --template ${PWD}/variable-service-template.yaml \ No newline at end of file diff --git a/examples/unfurl-technology-baseline-elastic/variable-service-template.yaml b/examples/unfurl-technology-baseline-elastic/variable-service-template.yaml new file mode 100644 index 0000000000..11925d898c --- /dev/null +++ b/examples/unfurl-technology-baseline-elastic/variable-service-template.yaml @@ -0,0 +1,53 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + gcp_region: + type: string + default: europe-west3 + + gcp_service_account_file: + type: string + default: /home/stoetzms/gcp/stoetzms-387808-2ec1cf865c76.json + + gcp_project: + type: string + default: stoetzms-387808 + + node_templates: + shop: + type: shop.component.terraform.gcp + properties: + application_name: unfurl-technology + DB_NAME: unfurl-technology + DB_USERNAME: root + DB_PASSWORD: {get_input: database_password} + DB_DIALECT: mysql + DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: database + - host: gcp_runtime + + database: + type: mysql.database.terraform.gcp + properties: + database_name: unfurl-technology + requirements: + - host: gcp_dbms + + gcp_dbms: + type: gcp.cloud_sql.terraform.gcp + properties: + instance_name: unfurl-technology + root_password: {get_input: database_password} + + gcp_runtime: + type: gcp.app_engine.terraform.gcp diff --git a/examples/unfurl-technology-baseline-kubernetes/.gitignore b/examples/unfurl-technology-baseline-kubernetes/.gitignore new file mode 100644 index 0000000000..4fe5ca855c --- /dev/null +++ b/examples/unfurl-technology-baseline-kubernetes/.gitignore @@ -0,0 +1,2 @@ +files +lib diff --git a/examples/unfurl-technology-baseline-kubernetes/config.yaml b/examples/unfurl-technology-baseline-kubernetes/config.yaml new file mode 100644 index 0000000000..8b7a206366 --- /dev/null +++ b/examples/unfurl-technology-baseline-kubernetes/config.yaml @@ -0,0 +1,3 @@ +dependencies: + - source: ../unfurl-technology-automated-weighted/lib + - source: ../unfurl-technology-automated-weighted/files diff --git a/examples/unfurl-technology-baseline-kubernetes/scripts/configuration.env b/examples/unfurl-technology-baseline-kubernetes/scripts/configuration.env new file mode 100644 index 0000000000..ac444e9970 --- /dev/null +++ b/examples/unfurl-technology-baseline-kubernetes/scripts/configuration.env @@ -0,0 +1,3 @@ +TEMPLATE_NAME="technology-kubernetes" +#VINTNER="node ../../../build/cli/index.js" +VINTNER="yarn cli" diff --git a/examples/unfurl-technology-baseline-kubernetes/scripts/configuration.sh b/examples/unfurl-technology-baseline-kubernetes/scripts/configuration.sh new file mode 100644 index 0000000000..d3d3ae4844 --- /dev/null +++ b/examples/unfurl-technology-baseline-kubernetes/scripts/configuration.sh @@ -0,0 +1,23 @@ +#! /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 + +# Set template directory +TEMPLATE_DIR=$(readlink -f $(dirname $0)/../) diff --git a/examples/unfurl-technology-baseline-kubernetes/scripts/quality.sh b/examples/unfurl-technology-baseline-kubernetes/scripts/quality.sh new file mode 100644 index 0000000000..aab83cf22c --- /dev/null +++ b/examples/unfurl-technology-baseline-kubernetes/scripts/quality.sh @@ -0,0 +1,8 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +# Quality +$VINTNER template quality --template ${TEMPLATE_DIR}/variable-service-template.yaml \ No newline at end of file diff --git a/examples/unfurl-technology-baseline-kubernetes/stats.sh b/examples/unfurl-technology-baseline-kubernetes/stats.sh new file mode 100644 index 0000000000..7cb56a56ac --- /dev/null +++ b/examples/unfurl-technology-baseline-kubernetes/stats.sh @@ -0,0 +1,4 @@ +#!/usr/bin/bash +set -e + +yarn cli template stats --template ${PWD}/variable-service-template.yaml \ No newline at end of file diff --git a/examples/unfurl-technology-baseline-kubernetes/variable-service-template.yaml b/examples/unfurl-technology-baseline-kubernetes/variable-service-template.yaml new file mode 100644 index 0000000000..521185a2f1 --- /dev/null +++ b/examples/unfurl-technology-baseline-kubernetes/variable-service-template.yaml @@ -0,0 +1,73 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + k8s_api_address: + type: string + default: 192.168.85.2 + + k8s_api_port: + type: string + default: '8443' + + k8s_ca_cert_file: + type: string + default: /home/stoetzms/.minikube/ca.crt + + k8s_client_cert_file: + type: string + default: /home/stoetzms/.minikube/profiles/minikube/client.crt + + k8s_client_key_file: + type: string + default: /home/stoetzms/.minikube/profiles/minikube/client.key + + node_templates: + shop: + type: shop.component.kubernetes.kubernetes + properties: + application_name: unfurl-technology + DB_NAME: unfurl-technology + DB_USERNAME: root + DB_PASSWORD: {get_input: database_password} + DB_DIALECT: mysql + DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: database + - host: kubernetes + + shop_expose: + type: shop.component.expose.kubernetes.kubernetes + requirements: + - host: kubernetes + + database: + type: mysql.database.ansible.mysql + properties: + database_name: unfurl-technology + requirements: + - host: mysql_dbms + - depends: mysql_dbms_expose + + mysql_dbms: + type: mysql.dbms.kubernetes.kubernetes + properties: + root_password: {get_input: database_password} + requirements: + - host: kubernetes + + mysql_dbms_expose: + type: mysql.dbms.expose.kubernetes.kubernetes + requirements: + - host: kubernetes + + kubernetes: + type: kubernetes diff --git a/examples/unfurl-technology-baseline-static-large/.gitignore b/examples/unfurl-technology-baseline-static-large/.gitignore new file mode 100644 index 0000000000..4fe5ca855c --- /dev/null +++ b/examples/unfurl-technology-baseline-static-large/.gitignore @@ -0,0 +1,2 @@ +files +lib diff --git a/examples/unfurl-technology-baseline-static-large/config.yaml b/examples/unfurl-technology-baseline-static-large/config.yaml new file mode 100644 index 0000000000..8b7a206366 --- /dev/null +++ b/examples/unfurl-technology-baseline-static-large/config.yaml @@ -0,0 +1,3 @@ +dependencies: + - source: ../unfurl-technology-automated-weighted/lib + - source: ../unfurl-technology-automated-weighted/files diff --git a/examples/unfurl-technology-baseline-static-large/scripts/configuration.env b/examples/unfurl-technology-baseline-static-large/scripts/configuration.env new file mode 100644 index 0000000000..c23f76aa4a --- /dev/null +++ b/examples/unfurl-technology-baseline-static-large/scripts/configuration.env @@ -0,0 +1,3 @@ +TEMPLATE_NAME="technology-static-large" +#VINTNER="node ../../../build/cli/index.js" +VINTNER="yarn cli" diff --git a/examples/unfurl-technology-baseline-static-large/scripts/configuration.sh b/examples/unfurl-technology-baseline-static-large/scripts/configuration.sh new file mode 100644 index 0000000000..d3d3ae4844 --- /dev/null +++ b/examples/unfurl-technology-baseline-static-large/scripts/configuration.sh @@ -0,0 +1,23 @@ +#! /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 + +# Set template directory +TEMPLATE_DIR=$(readlink -f $(dirname $0)/../) diff --git a/examples/unfurl-technology-baseline-static-large/scripts/quality.sh b/examples/unfurl-technology-baseline-static-large/scripts/quality.sh new file mode 100644 index 0000000000..aab83cf22c --- /dev/null +++ b/examples/unfurl-technology-baseline-static-large/scripts/quality.sh @@ -0,0 +1,8 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +# Quality +$VINTNER template quality --template ${TEMPLATE_DIR}/variable-service-template.yaml \ No newline at end of file diff --git a/examples/unfurl-technology-baseline-static-large/stats.sh b/examples/unfurl-technology-baseline-static-large/stats.sh new file mode 100644 index 0000000000..7cb56a56ac --- /dev/null +++ b/examples/unfurl-technology-baseline-static-large/stats.sh @@ -0,0 +1,4 @@ +#!/usr/bin/bash +set -e + +yarn cli template stats --template ${PWD}/variable-service-template.yaml \ No newline at end of file diff --git a/examples/unfurl-technology-baseline-static-large/variable-service-template.yaml b/examples/unfurl-technology-baseline-static-large/variable-service-template.yaml new file mode 100644 index 0000000000..821333ee2e --- /dev/null +++ b/examples/unfurl-technology-baseline-static-large/variable-service-template.yaml @@ -0,0 +1,90 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + os_network: + type: string + default: public-belwue + + os_ssh_key_name: + type: string + default: default + + os_ssh_user: + type: string + default: ubuntu + + os_ssh_key_file: + type: string + default: /home/stoetzms/.ssh/bw-cloud--default + + os_region_name: + type: string + default: Mannheim + + os_auth_type: + type: string + default: v3applicationcredential + + os_auth_url: + type: string + default: https://idm02.bw-cloud.org:5000/v3 + + os_identity_api_version: + type: string + default: '3' + + os_interface: + type: string + default: public + + os_application_credential_id: + type: string + default: 3f538f1823bd484e8238b2433de2f21a + + os_application_credential_secret: + type: string + + node_templates: + shop: + type: shop.component.ansible.os + properties: + application_name: unfurl-technology + DB_NAME: unfurl-technology + DB_USERNAME: root + DB_PASSWORD: {get_input: database_password} + DB_DIALECT: mysql + DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: database + - host: os_compute + + database: + type: mysql.database.ansible.mysql + properties: + database_name: unfurl-technology + requirements: + - host: mysql_dbms + + mysql_dbms: + type: mysql.dbms.ansible.os + properties: + root_password: {get_input: database_password} + requirements: + - host: os_compute + + os_compute: + type: os.compute.terraform.os + properties: + machine: unfurl-technology + ports: [80, 3000] + network: {get_input: os_network} + flavor: m1.large diff --git a/examples/unfurl-technology-baseline-static/.gitignore b/examples/unfurl-technology-baseline-static/.gitignore new file mode 100644 index 0000000000..4fe5ca855c --- /dev/null +++ b/examples/unfurl-technology-baseline-static/.gitignore @@ -0,0 +1,2 @@ +files +lib diff --git a/examples/unfurl-technology-baseline-static/config.yaml b/examples/unfurl-technology-baseline-static/config.yaml new file mode 100644 index 0000000000..8b7a206366 --- /dev/null +++ b/examples/unfurl-technology-baseline-static/config.yaml @@ -0,0 +1,3 @@ +dependencies: + - source: ../unfurl-technology-automated-weighted/lib + - source: ../unfurl-technology-automated-weighted/files diff --git a/examples/unfurl-technology-baseline-static/scripts/configuration.env b/examples/unfurl-technology-baseline-static/scripts/configuration.env new file mode 100644 index 0000000000..b175407e3a --- /dev/null +++ b/examples/unfurl-technology-baseline-static/scripts/configuration.env @@ -0,0 +1,3 @@ +TEMPLATE_NAME="technology-static" +#VINTNER="node ../../../build/cli/index.js" +VINTNER="yarn cli" diff --git a/examples/unfurl-technology-baseline-static/scripts/configuration.sh b/examples/unfurl-technology-baseline-static/scripts/configuration.sh new file mode 100644 index 0000000000..d3d3ae4844 --- /dev/null +++ b/examples/unfurl-technology-baseline-static/scripts/configuration.sh @@ -0,0 +1,23 @@ +#! /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 + +# Set template directory +TEMPLATE_DIR=$(readlink -f $(dirname $0)/../) diff --git a/examples/unfurl-technology-baseline-static/scripts/quality.sh b/examples/unfurl-technology-baseline-static/scripts/quality.sh new file mode 100644 index 0000000000..aab83cf22c --- /dev/null +++ b/examples/unfurl-technology-baseline-static/scripts/quality.sh @@ -0,0 +1,8 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +# Quality +$VINTNER template quality --template ${TEMPLATE_DIR}/variable-service-template.yaml \ No newline at end of file diff --git a/examples/unfurl-technology-baseline-static/stats.sh b/examples/unfurl-technology-baseline-static/stats.sh new file mode 100644 index 0000000000..7cb56a56ac --- /dev/null +++ b/examples/unfurl-technology-baseline-static/stats.sh @@ -0,0 +1,4 @@ +#!/usr/bin/bash +set -e + +yarn cli template stats --template ${PWD}/variable-service-template.yaml \ No newline at end of file diff --git a/examples/unfurl-technology-baseline-static/variable-service-template.yaml b/examples/unfurl-technology-baseline-static/variable-service-template.yaml new file mode 100644 index 0000000000..c4cf4773b7 --- /dev/null +++ b/examples/unfurl-technology-baseline-static/variable-service-template.yaml @@ -0,0 +1,90 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + os_network: + type: string + default: public-belwue + + os_ssh_key_name: + type: string + default: default + + os_ssh_user: + type: string + default: ubuntu + + os_ssh_key_file: + type: string + default: /home/stoetzms/.ssh/bw-cloud--default + + os_region_name: + type: string + default: Mannheim + + os_auth_type: + type: string + default: v3applicationcredential + + os_auth_url: + type: string + default: https://idm02.bw-cloud.org:5000/v3 + + os_identity_api_version: + type: string + default: '3' + + os_interface: + type: string + default: public + + os_application_credential_id: + type: string + default: 3f538f1823bd484e8238b2433de2f21a + + os_application_credential_secret: + type: string + + node_templates: + shop: + type: shop.component.ansible.os + properties: + application_name: unfurl-technology + DB_NAME: unfurl-technology + DB_USERNAME: root + DB_PASSWORD: {get_input: database_password} + DB_DIALECT: mysql + DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: database + - host: os_compute + + database: + type: mysql.database.ansible.mysql + properties: + database_name: unfurl-technology + requirements: + - host: mysql_dbms + + mysql_dbms: + type: mysql.dbms.ansible.os + properties: + root_password: {get_input: database_password} + requirements: + - host: os_compute + + os_compute: + type: os.compute.terraform.os + properties: + machine: unfurl-technology + ports: [80, 3000] + network: {get_input: os_network} + flavor: m1.medium diff --git a/examples/unfurl-technology-maintenance/.gitignore b/examples/unfurl-technology-maintenance/.gitignore new file mode 100644 index 0000000000..4fe5ca855c --- /dev/null +++ b/examples/unfurl-technology-maintenance/.gitignore @@ -0,0 +1,2 @@ +files +lib diff --git a/examples/unfurl-technology-maintenance/config.yaml b/examples/unfurl-technology-maintenance/config.yaml new file mode 100644 index 0000000000..8b7a206366 --- /dev/null +++ b/examples/unfurl-technology-maintenance/config.yaml @@ -0,0 +1,3 @@ +dependencies: + - source: ../unfurl-technology-automated-weighted/lib + - source: ../unfurl-technology-automated-weighted/files diff --git a/examples/unfurl-technology-maintenance/stats.sh b/examples/unfurl-technology-maintenance/stats.sh new file mode 100644 index 0000000000..7cb56a56ac --- /dev/null +++ b/examples/unfurl-technology-maintenance/stats.sh @@ -0,0 +1,4 @@ +#!/usr/bin/bash +set -e + +yarn cli template stats --template ${PWD}/variable-service-template.yaml \ No newline at end of file diff --git a/examples/unfurl-technology-maintenance/tests/elastic/test.yaml b/examples/unfurl-technology-maintenance/tests/elastic/test.yaml new file mode 100644 index 0000000000..ea8db06698 --- /dev/null +++ b/examples/unfurl-technology-maintenance/tests/elastic/test.yaml @@ -0,0 +1,2 @@ +expected: ../../../unfurl-technology-baseline-elastic/variable-service-template.yaml +presets: elastic diff --git a/examples/unfurl-technology-maintenance/tests/kubernetes/test.yaml b/examples/unfurl-technology-maintenance/tests/kubernetes/test.yaml new file mode 100644 index 0000000000..c417424471 --- /dev/null +++ b/examples/unfurl-technology-maintenance/tests/kubernetes/test.yaml @@ -0,0 +1,2 @@ +expected: ../../../unfurl-technology-baseline-kubernetes/variable-service-template.yaml +presets: kubernetes diff --git a/examples/unfurl-technology-maintenance/tests/static-large/test.yaml b/examples/unfurl-technology-maintenance/tests/static-large/test.yaml new file mode 100644 index 0000000000..4b3ef3f31d --- /dev/null +++ b/examples/unfurl-technology-maintenance/tests/static-large/test.yaml @@ -0,0 +1,2 @@ +expected: ../../../unfurl-technology-baseline-static-large/variable-service-template.yaml +presets: static-large diff --git a/examples/unfurl-technology-maintenance/tests/static/test.yaml b/examples/unfurl-technology-maintenance/tests/static/test.yaml new file mode 100644 index 0000000000..58d9cdacfa --- /dev/null +++ b/examples/unfurl-technology-maintenance/tests/static/test.yaml @@ -0,0 +1,2 @@ +expected: ../../../unfurl-technology-baseline-static/variable-service-template.yaml +presets: static diff --git a/examples/unfurl-technology-maintenance/variable-service-template.yaml b/examples/unfurl-technology-maintenance/variable-service-template.yaml new file mode 100644 index 0000000000..7cfcb00a78 --- /dev/null +++ b/examples/unfurl-technology-maintenance/variable-service-template.yaml @@ -0,0 +1,252 @@ +tosca_definitions_version: tosca_variability_1_0 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + os_network: + type: string + default: public-belwue + conditions: {logic_expression: is_static} + + os_ssh_key_name: + type: string + default: default + conditions: {logic_expression: is_static} + + os_ssh_user: + type: string + default: ubuntu + conditions: {logic_expression: is_static} + + os_ssh_key_file: + type: string + default: /home/stoetzms/.ssh/bw-cloud--default + conditions: {logic_expression: is_static} + + os_region_name: + type: string + default: Mannheim + conditions: {logic_expression: is_static} + + os_auth_type: + type: string + default: v3applicationcredential + conditions: {logic_expression: is_static} + + os_auth_url: + type: string + default: https://idm02.bw-cloud.org:5000/v3 + conditions: {logic_expression: is_static} + + os_identity_api_version: + type: string + default: '3' + conditions: {logic_expression: is_static} + + os_interface: + type: string + default: public + conditions: {logic_expression: is_static} + + os_application_credential_id: + type: string + default: 3f538f1823bd484e8238b2433de2f21a + conditions: {logic_expression: is_static} + + os_application_credential_secret: + type: string + conditions: {logic_expression: is_static} + + gcp_region: + type: string + default: europe-west3 + conditions: {logic_expression: is_elastic} + + gcp_service_account_file: + type: string + default: /home/stoetzms/gcp/stoetzms-387808-2ec1cf865c76.json + conditions: {logic_expression: is_elastic} + + gcp_project: + type: string + default: stoetzms-387808 + conditions: {logic_expression: is_elastic} + + k8s_api_address: + type: string + default: 192.168.85.2 + conditions: {logic_expression: is_kubernetes} + + k8s_api_port: + type: string + default: '8443' + conditions: {logic_expression: is_kubernetes} + + k8s_ca_cert_file: + type: string + default: /home/stoetzms/.minikube/ca.crt + conditions: {logic_expression: is_kubernetes} + + k8s_client_cert_file: + type: string + default: /home/stoetzms/.minikube/profiles/minikube/client.crt + conditions: {logic_expression: is_kubernetes} + + k8s_client_key_file: + type: string + default: /home/stoetzms/.minikube/profiles/minikube/client.key + conditions: {logic_expression: is_kubernetes} + + variability: + inputs: + env: + type: string + default: STATIC + + medium: + type: boolean + default: true + + presets: + static: + inputs: + env: STATIC + + static-large: + inputs: + env: STATIC + medium: false + + elastic: + inputs: + env: ELASTIC + + kubernetes: + inputs: + env: KUBERNETES + + expressions: + is_static: {equal: [{variability_input: env}, STATIC]} + is_elastic: {equal: [{variability_input: env}, ELASTIC]} + is_kubernetes: {equal: [{variability_input: env}, KUBERNETES]} + + is_medium: {variability_input: medium} + is_large: {not: {logic_expression: is_medium}} + + options: + mode: semantic-loose + + node_default_condition_mode: incomingnaive-host + hosting_stack_constraint: true + + optimization_topology: true + optimization_topology_unique: true + + technology_pruning: true + technology_constraint: false + + optimization_technologies: max + optimization_technologies_mode: weight + + node_templates: + shop: + type: shop.component + persistent: true + properties: + - application_name: unfurl-technology + - DB_NAME: unfurl-technology + - DB_USERNAME: root + - DB_PASSWORD: {get_input: database_password} + - DB_DIALECT: mysql + - DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + - DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: + node: database + + - host: + node: os_compute + conditions: {logic_expression: is_static} + + - host: + node: gcp_runtime + conditions: {logic_expression: is_elastic} + + - host: + node: kubernetes + conditions: {logic_expression: is_kubernetes} + + shop_expose: + type: shop.component.expose.kubernetes.kubernetes + conditions: {logic_expression: is_kubernetes} + requirements: + - host: kubernetes + + database: + type: mysql.database + persistent: true + properties: + - database_name: unfurl-technology + requirements: + - host: + node: mysql_dbms + conditions: {or: [{logic_expression: is_static}, {logic_expression: is_kubernetes}]} + + - host: + node: gcp_dbms + conditions: {logic_expression: is_elastic} + + - depends: + node: mysql_dbms_expose + implied: true + conditions: {logic_expression: is_kubernetes} + + mysql_dbms: + type: mysql.dbms + properties: + - root_password: {get_input: database_password} + requirements: + - host: + node: os_compute + conditions: {logic_expression: is_static} + + - host: + node: kubernetes + conditions: {logic_expression: is_kubernetes} + + mysql_dbms_expose: + type: mysql.dbms.expose.kubernetes.kubernetes + requirements: + - host: kubernetes + + os_compute: + type: os.compute + properties: + - machine: unfurl-technology + - ports: [80, 3000] + - network: {get_input: os_network} + - flavor: + value: m1.medium + conditions: {logic_expression: is_medium} + + - flavor: + value: m1.large + conditions: {logic_expression: is_large} + + gcp_dbms: + type: gcp.cloud_sql + properties: + - instance_name: unfurl-technology + - root_password: {get_input: database_password} + + gcp_runtime: + type: gcp.app_engine + + kubernetes: + type: kubernetes diff --git a/examples/unfurl-technology-manual/.gitignore b/examples/unfurl-technology-manual/.gitignore new file mode 100644 index 0000000000..4fe5ca855c --- /dev/null +++ b/examples/unfurl-technology-manual/.gitignore @@ -0,0 +1,2 @@ +files +lib diff --git a/examples/unfurl-technology-manual/config.yaml b/examples/unfurl-technology-manual/config.yaml new file mode 100644 index 0000000000..8b7a206366 --- /dev/null +++ b/examples/unfurl-technology-manual/config.yaml @@ -0,0 +1,3 @@ +dependencies: + - source: ../unfurl-technology-automated-weighted/lib + - source: ../unfurl-technology-automated-weighted/files diff --git a/examples/unfurl-technology-manual/stats.sh b/examples/unfurl-technology-manual/stats.sh new file mode 100644 index 0000000000..7cb56a56ac --- /dev/null +++ b/examples/unfurl-technology-manual/stats.sh @@ -0,0 +1,4 @@ +#!/usr/bin/bash +set -e + +yarn cli template stats --template ${PWD}/variable-service-template.yaml \ No newline at end of file diff --git a/examples/unfurl-technology-manual/tests/elastic/test.yaml b/examples/unfurl-technology-manual/tests/elastic/test.yaml new file mode 100644 index 0000000000..ea8db06698 --- /dev/null +++ b/examples/unfurl-technology-manual/tests/elastic/test.yaml @@ -0,0 +1,2 @@ +expected: ../../../unfurl-technology-baseline-elastic/variable-service-template.yaml +presets: elastic diff --git a/examples/unfurl-technology-manual/tests/static-large/test.yaml b/examples/unfurl-technology-manual/tests/static-large/test.yaml new file mode 100644 index 0000000000..4b3ef3f31d --- /dev/null +++ b/examples/unfurl-technology-manual/tests/static-large/test.yaml @@ -0,0 +1,2 @@ +expected: ../../../unfurl-technology-baseline-static-large/variable-service-template.yaml +presets: static-large diff --git a/examples/unfurl-technology-manual/tests/static/test.yaml b/examples/unfurl-technology-manual/tests/static/test.yaml new file mode 100644 index 0000000000..58d9cdacfa --- /dev/null +++ b/examples/unfurl-technology-manual/tests/static/test.yaml @@ -0,0 +1,2 @@ +expected: ../../../unfurl-technology-baseline-static/variable-service-template.yaml +presets: static diff --git a/examples/unfurl-technology-manual/variable-service-template.yaml b/examples/unfurl-technology-manual/variable-service-template.yaml new file mode 100644 index 0000000000..97bec0b72d --- /dev/null +++ b/examples/unfurl-technology-manual/variable-service-template.yaml @@ -0,0 +1,207 @@ +tosca_definitions_version: tosca_variability_1_0 + +imports: + - lib/types.yaml + +topology_template: + inputs: + database_password: + type: string + default: password + + os_network: + type: string + default: public-belwue + conditions: {logic_expression: is_static} + + os_ssh_key_name: + type: string + default: default + conditions: {logic_expression: is_static} + + os_ssh_user: + type: string + default: ubuntu + conditions: {logic_expression: is_static} + + os_ssh_key_file: + type: string + default: /home/stoetzms/.ssh/bw-cloud--default + conditions: {logic_expression: is_static} + + os_region_name: + type: string + default: Mannheim + conditions: {logic_expression: is_static} + + os_auth_type: + type: string + default: v3applicationcredential + conditions: {logic_expression: is_static} + + os_auth_url: + type: string + default: https://idm02.bw-cloud.org:5000/v3 + conditions: {logic_expression: is_static} + + os_identity_api_version: + type: string + default: '3' + conditions: {logic_expression: is_static} + + os_interface: + type: string + default: public + conditions: {logic_expression: is_static} + + os_application_credential_id: + type: string + default: 3f538f1823bd484e8238b2433de2f21a + conditions: {logic_expression: is_static} + + os_application_credential_secret: + type: string + conditions: {logic_expression: is_static} + + gcp_region: + type: string + default: europe-west3 + conditions: {logic_expression: is_elastic} + + gcp_service_account_file: + type: string + default: /home/stoetzms/gcp/stoetzms-387808-2ec1cf865c76.json + conditions: {logic_expression: is_elastic} + + gcp_project: + type: string + default: stoetzms-387808 + conditions: {logic_expression: is_elastic} + + variability: + inputs: + env: + type: string + default: STATIC + + medium: + type: boolean + default: true + + presets: + static: + inputs: + env: STATIC + + static-large: + inputs: + env: STATIC + medium: false + + elastic: + inputs: + env: ELASTIC + + expressions: + is_static: {equal: [{variability_input: env}, STATIC]} + is_elastic: {equal: [{variability_input: env}, ELASTIC]} + + is_medium: {variability_input: medium} + is_large: {not: {logic_expression: is_medium}} + + options: + mode: semantic-loose + + node_default_condition_mode: incomingnaive-host + hosting_stack_constraint: true + + optimization_topology: true + optimization_topology_unique: true + + technology_pruning: true + technology_constraint: true + + optimization_technologies: true + + node_templates: + shop: + type: shop.component + persistent: true + technology: + - ansible: + conditions: {logic_expression: is_static} + - terraform: + conditions: {logic_expression: is_elastic} + properties: + - application_name: unfurl-technology + - DB_NAME: unfurl-technology + - DB_USERNAME: root + - DB_PASSWORD: {get_input: database_password} + - DB_DIALECT: mysql + - DB_ADDRESS: {eval: '.::.requirements[.name=database]::.target::application_address'} + - DB_PORT: {eval: '.::.requirements[.name=database]::.target::application_port'} + requirements: + - database: + node: database + + - host: + node: os_compute + conditions: {logic_expression: is_static} + + - host: + node: gcp_runtime + conditions: {logic_expression: is_elastic} + + database: + type: mysql.database + persistent: true + technology: + - ansible: + conditions: {logic_expression: is_static} + - terraform: + conditions: {logic_expression: is_elastic} + properties: + - database_name: unfurl-technology + requirements: + - host: + node: mysql_dbms + conditions: {logic_expression: is_static} + + - host: + node: gcp_dbms + conditions: {logic_expression: is_elastic} + + mysql_dbms: + type: mysql.dbms + technology: ansible + properties: + - root_password: {get_input: database_password} + requirements: + - host: + node: os_compute + + os_compute: + type: os.compute + technology: terraform + properties: + - machine: unfurl-technology + - ports: [80, 3000] + - network: {get_input: os_network} + - flavor: + value: m1.medium + conditions: {logic_expression: is_medium} + + - flavor: + value: m1.large + conditions: {logic_expression: is_large} + + gcp_dbms: + type: gcp.cloud_sql + technology: terraform + properties: + - instance_name: unfurl-technology + - root_password: {get_input: database_password} + + gcp_runtime: + type: gcp.app_engine + technology: terraform diff --git a/package.json b/package.json index 84021dcb01..b992a99d7d 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "is-wsl": "^2.2.0", "js-yaml": "^4.1.0", "json-diff": "^1.0.3", + "lnk": "^1.1.0", "lodash": "^4.17.21", "logic-solver": "^2.0.1", "node-cron": "^3.0.2", @@ -158,6 +159,7 @@ "docs:export": "bash docs/cmds/export/generate.sh", "docs:export:local": "bash docs/cmds/export/generate.sh http://localhost:8000", "examples:pull": "bash cmds/pull-examples.sh", + "examples:pull:link": "bash cmds/pull-examples.sh true", "examples:generate:getting-started": "yarn cli template init --path examples/xopera-getting-started --force", "examples:xopera": "bash examples/xopera-motivation/demo.sh", "examples:unfurl": "bash examples/unfurl-motivation/demo.sh", diff --git a/patches/lnk+1.1.0.patch b/patches/lnk+1.1.0.patch new file mode 100644 index 0000000000..c09f4fd928 --- /dev/null +++ b/patches/lnk+1.1.0.patch @@ -0,0 +1,9 @@ +diff --git a/node_modules/lnk/index.d.ts b/node_modules/lnk/index.d.ts +new file mode 100644 +index 0000000..dd15ad1 +--- /dev/null ++++ b/node_modules/lnk/index.d.ts +@@ -0,0 +1,3 @@ ++declare module 'lnk' { ++ export default function(source: string, target: string, options: {force?: boolean}): Promise ++} diff --git a/src/assets/scripts/install-unfurl.sh b/src/assets/scripts/install-unfurl.sh index 7de7eae7ff..99bb3e5862 100755 --- a/src/assets/scripts/install-unfurl.sh +++ b/src/assets/scripts/install-unfurl.sh @@ -27,4 +27,5 @@ cd "${VENV_DIR}" python3 -m venv .venv && . .venv/bin/activate # Install Unfurl -pip install unfurl==1.0.0 openstacksdk==0.61 python-openstackclient==6.0.0 ansible==4.10.0 +# See also https://github.com/onecommons/unfurl/blob/main/full-requirements.txt +pip install unfurl==1.0.0 openstacksdk==0.61 python-openstackclient==6.0.0 ansible==4.10.0 pymysql==1.1.0 kubernetes==24.2.0 openshift==0.13.2 diff --git a/src/assets/scripts/install-xopera.sh b/src/assets/scripts/install-xopera.sh index 26685529df..0720aa610d 100755 --- a/src/assets/scripts/install-xopera.sh +++ b/src/assets/scripts/install-xopera.sh @@ -29,4 +29,4 @@ python3 -m venv .venv && . .venv/bin/activate # Install xOpera # openstacksdk 0.61 is required, see https://storyboard.openstack.org/#!/story/2010128 # pyyaml 5.3.1 is required, see https://github.com/yaml/pyyaml/issues/724#issuecomment-1638587228 -pip install opera==0.6.9 openstacksdk==0.61 python-openstackclient==6.0.0 pyyaml==5.3.1 ansible==4.10.0 +pip install opera==0.6.9 openstacksdk==0.61 python-openstackclient==6.0.0 pyyaml==5.3.1 ansible==4.10.0 pymysql==1.1.0 diff --git a/src/assets/templates/template-init/scripts/pull.sh b/src/assets/templates/template-init/scripts/pull.sh old mode 100644 new mode 100755 diff --git a/src/assets/templates/template-init/scripts/quality.sh b/src/assets/templates/template-init/scripts/quality.sh new file mode 100755 index 0000000000..aab83cf22c --- /dev/null +++ b/src/assets/templates/template-init/scripts/quality.sh @@ -0,0 +1,8 @@ +#! /usr/bin/bash +set -e + +# Load configuration +source configuration.sh + +# Quality +$VINTNER template quality --template ${TEMPLATE_DIR}/variable-service-template.yaml \ No newline at end of file diff --git a/src/cli/program.ts b/src/cli/program.ts index 0aedd2355e..a10a162e39 100644 --- a/src/cli/program.ts +++ b/src/cli/program.ts @@ -455,7 +455,8 @@ template template .command('pull') .description('pull template dependencies') - .requiredOption('--template ', 'path to service template') + .requiredOption('--template ', 'path to service template directory') + .option('--link [boolean]', 'create symbolic links instead of copying files', false) .action( hae.exit(async options => { await Controller.template.pull(options) @@ -659,6 +660,7 @@ instances .requiredOption('--instance ', 'instance name') .option('--inputs [string]', 'path to the deployment inputs') .option('--verbose [boolean]', 'verbose') + .option('--dry [boolean]', 'dry run') .action( hae.exit(async options => { await Controller.instances.validate(options) diff --git a/src/controller/instances/adapt.ts b/src/controller/instances/adapt.ts index 59b20cb49d..64951c4832 100644 --- a/src/controller/instances/adapt.ts +++ b/src/controller/instances/adapt.ts @@ -73,7 +73,7 @@ emitter.on(events.start_adaptation, async (instance: Instance) => { * Analyze: Resolve variability */ const result = await Resolver.run({ - template: instance.loadVariableServiceTemplate(), + template: instance.getVariableServiceTemplate(), inputs: cache[instance.getName()], }) diff --git a/src/controller/instances/resolve.ts b/src/controller/instances/resolve.ts index 91f3a16edc..d56d30532d 100644 --- a/src/controller/instances/resolve.ts +++ b/src/controller/instances/resolve.ts @@ -16,7 +16,7 @@ export default async function (options: InstanceResolveOptions) { await lock.try(instance.getLockKey(), async () => { // Resolve variability const result = await Resolver.run({ - template: instance.loadVariableServiceTemplate(), + template: instance.getVariableServiceTemplate(), inputs: options.inputs, presets: options.presets, }) diff --git a/src/controller/instances/validate.ts b/src/controller/instances/validate.ts index 7897639e61..302580bdec 100644 --- a/src/controller/instances/validate.ts +++ b/src/controller/instances/validate.ts @@ -2,13 +2,15 @@ import orchestrators from '#orchestrators' import {Instance} from '#repositories/instances' import lock from '#utils/lock' -export type InstancesValidateOptions = {instance: string; verbose?: boolean; inputs?: string} +export type InstancesValidateOptions = {instance: string; verbose?: boolean; inputs?: string; dry?: boolean} export default async function (options: InstancesValidateOptions) { const instance = new Instance(options.instance) await lock.try(instance.getLockKey(), async () => { if (!instance.exists()) throw new Error(`Instance "${instance.getName()}" does not exist`) - await orchestrators.get().validate(instance, {verbose: options.verbose, inputs: options.inputs}) + await orchestrators + .get() + .validate(instance, {verbose: options.verbose, inputs: options.inputs, dry: options.dry}) }) } diff --git a/src/controller/setup/benchmark.ts b/src/controller/setup/benchmark.ts index 39ffc85b5d..cdc9f7a5d3 100644 --- a/src/controller/setup/benchmark.ts +++ b/src/controller/setup/benchmark.ts @@ -52,7 +52,7 @@ export default async function (options: BenchmarkOptions) { if (io) files.storeYAML(input, serviceTemplate) const result = await Resolver.run({ - template: io ? files.loadYAML(input) : serviceTemplate, + template: io ? input : serviceTemplate, inputs: {mode: 'present'}, }) diff --git a/src/controller/template/normalize.ts b/src/controller/template/normalize.ts index 0e2a4b146d..0c0309928e 100644 --- a/src/controller/template/normalize.ts +++ b/src/controller/template/normalize.ts @@ -1,7 +1,7 @@ import * as assert from '#assert' import * as files from '#files' +import Loader from '#graph/loader' import Normalizer from '#normalizer' -import {ServiceTemplate} from '#spec/service-template' export type TemplateNormalizeOptions = { template: string @@ -11,7 +11,7 @@ export type TemplateNormalizeOptions = { export default async function (options: TemplateNormalizeOptions) { assert.isDefined(options.template, 'Template not defined') assert.isDefined(options.output, 'Output not defined') - const template = files.loadYAML(options.template) + const template = new Loader(options.template).raw() new Normalizer(template).run() files.storeYAML(options.output, template) } diff --git a/src/controller/template/pull.ts b/src/controller/template/pull.ts index ad76a0bf45..8c16486b51 100644 --- a/src/controller/template/pull.ts +++ b/src/controller/template/pull.ts @@ -4,6 +4,7 @@ import path from 'path' export type TemplatePullOptions = { template: string + link?: boolean } export type Config = { @@ -13,7 +14,7 @@ export type Config = { export type Dependencies = TemplateDependency[] export type TemplateDependency = { source: string - target: string + target?: string } export default async function (options: TemplatePullOptions) { @@ -27,10 +28,16 @@ export default async function (options: TemplatePullOptions) { for (const dependency of config.dependencies) { assert.isString(dependency.source) - assert.isString(dependency.target) - await files.sync( - path.isAbsolute(dependency.source) ? dependency.source : path.join(options.template, dependency.source), - path.join(options.template, dependency.target) - ) + + const source = path.isAbsolute(dependency.source) + ? dependency.source + : path.join(options.template, dependency.source) + const target = path.join(options.template, dependency.target || '.') + + if (options.link) { + await files.link(source, target) + } else { + await files.sync(source, target) + } } } diff --git a/src/controller/template/puml/topology.ts b/src/controller/template/puml/topology.ts index 313f9d93cd..51d22ad4f4 100644 --- a/src/controller/template/puml/topology.ts +++ b/src/controller/template/puml/topology.ts @@ -1,7 +1,7 @@ import * as assert from '#assert' import * as files from '#files' import Graph from '#graph/graph' -import {ServiceTemplate} from '#spec/service-template' +import Loader from '#graph/loader' import std from '#std' import * as utils from '#utils' import path from 'path' @@ -18,7 +18,7 @@ export default async function (options: TemplatePUMLTopologyOptions) { const output = options.output ?? options.path.replace(/(\.yaml|\.yml)/, '.topology.puml') if (!output.endsWith('.puml')) throw new Error(`Output path "${output}" does not end with '.puml'`) - const graph = new Graph(files.loadYAML(options.path)) + const graph = new Graph(new Loader(options.path).raw()) validate(graph) const plot = await files.renderFile(path.join(files.TEMPLATES_DIR, 'puml', 'topology', 'template.template.ejs'), { diff --git a/src/controller/template/puml/types.ts b/src/controller/template/puml/types.ts index 7ac76477a5..ce6723815b 100644 --- a/src/controller/template/puml/types.ts +++ b/src/controller/template/puml/types.ts @@ -1,7 +1,7 @@ import * as assert from '#assert' import * as files from '#files' import Graph from '#graph/graph' -import {ServiceTemplate} from '#spec/service-template' +import Loader from '#graph/loader' import std from '#std' import * as utils from '#utils' import path from 'path' @@ -19,7 +19,7 @@ export default async function (options: TemplatePUMLTypesOptions) { const outputDir = options.output ?? files.getDirectory(options.path) files.assertDirectory(outputDir) - const graph = new Graph(files.loadYAML(options.path)) + const graph = new Graph(new Loader(options.path).raw()) const types = options.types ?? Object.keys(graph.serviceTemplate).filter(it => it.endsWith('_types')) diff --git a/src/controller/template/query.ts b/src/controller/template/query.ts index 7cef5080b3..41f4d80204 100644 --- a/src/controller/template/query.ts +++ b/src/controller/template/query.ts @@ -1,5 +1,6 @@ import * as check from '#check' import * as files from '#files' +import Loader from '#graph/loader' import {Query} from '#query/query' import {getParentNode} from '#query/utils' import {ServiceTemplate, TOSCA_DEFINITIONS_VERSION} from '#spec/service-template' @@ -10,7 +11,7 @@ export type TemplateQueryOptions = { } export default function (options: TemplateQueryOptions) { - const template = files.loadYAML(options.template) + const template = new Loader(options.template).raw() if (template.tosca_definitions_version !== TOSCA_DEFINITIONS_VERSION.TOSCA_SIMPLE_YAML_1_3) throw new Error(`TOSCA definitions version "${template.tosca_definitions_version}" not supported`) diff --git a/src/controller/template/stats.ts b/src/controller/template/stats.ts index c088a2957e..b9954b7727 100644 --- a/src/controller/template/stats.ts +++ b/src/controller/template/stats.ts @@ -3,7 +3,7 @@ import * as check from '#check' import * as files from '#files' import Element from '#graph/element' import Graph from '#graph/graph' -import {ServiceTemplate} from '#spec/service-template' +import Loader from '#graph/loader' import * as utils from '#utils' export type TemplateStatsOptions = { @@ -20,46 +20,62 @@ export type TemplateStats = { inputs: number artifacts: number imports: number + technologies: number elements: number - // Nodes + Relations + Properties + Artifacts - nrpa: number - manual_at_nrpa: number - generated_at_nrpa: number + // Nodes + Relations + Properties + Artifacts + (Manual) Technologies + edmm_elements: number + manual_at_edmm_elements: number + generated_at_edmm_elements: number + loc: number } export default async function (options: TemplateStatsOptions) { assert.isDefined(options.template, 'Template not defined') + // TODO: count technologies encoded in node type + return utils.sumObjects( - options.template.map(it => { - const graph = new Graph(files.loadYAML(it)) - const stats: TemplateStats = { - nodes: graph.nodes.length, - relations: graph.relations.length, - properties: graph.properties.length, - types: graph.types.length, - policies: graph.policies.length, - groups: graph.groups.length, - inputs: graph.inputs.length, - artifacts: graph.artifacts.length, - imports: graph.imports.length, - elements: graph.elements.length, - nrpa: graph.nodes.length + graph.relations.length + graph.properties.length + graph.artifacts.length, - manual_at_nrpa: countManualAtNRPA(graph), - generated_at_nrpa: countGeneratedAtNRPA(graph), - } - return stats - }) + await Promise.all( + options.template.map(async it => { + const template = await new Loader(it).load() + const graph = new Graph(template) + + const stats: TemplateStats = { + nodes: graph.nodes.length, + relations: graph.relations.length, + properties: graph.properties.length, + types: graph.types.length, + policies: graph.policies.length, + groups: graph.groups.length, + inputs: graph.inputs.length, + artifacts: graph.artifacts.length, + imports: graph.imports.length, + technologies: graph.technologies.length, + elements: graph.elements.length, + edmm_elements: + graph.nodes.length + + graph.relations.length + + graph.properties.length + + graph.artifacts.length + + graph.technologies.length, + manual_at_edmm_elements: countManualAtNRPAT(graph), + generated_at_edmm_elements: countGeneratedAtNRPAT(graph), + loc: files.countLines(it), + } + return stats + }) + ) ) } -function countManualAtNRPA(graph: Graph) { +function countManualAtNRPAT(graph: Graph) { let count = 0 graph.nodes.forEach(it => (count += countManual(it))) graph.relations.forEach(it => (count += countManual(it))) graph.properties.forEach(it => (count += countManual(it))) graph.artifacts.forEach(it => (count += countManual(it))) + graph.technologies.forEach(it => (count += countManual(it))) return count } @@ -87,13 +103,14 @@ function countManual(element: Element) { return count } -function countGeneratedAtNRPA(graph: Graph) { +function countGeneratedAtNRPAT(graph: Graph) { let count = 0 graph.nodes.forEach(it => (count += countGenerated(it))) graph.relations.forEach(it => (count += countGenerated(it))) graph.properties.forEach(it => (count += countGenerated(it))) graph.artifacts.forEach(it => (count += countGenerated(it))) + graph.technologies.forEach(it => (count += countGenerated(it))) return count } diff --git a/src/controller/template/test.ts b/src/controller/template/test.ts index d919ee2afd..cd6af78de9 100644 --- a/src/controller/template/test.ts +++ b/src/controller/template/test.ts @@ -1,7 +1,7 @@ import * as check from '#check' import Controller from '#controller' import * as files from '#files' -import {ServiceTemplate} from '#spec/service-template' +import Loader from '#graph/loader' import std from '#std' import * as utils from '#utils' import jsonDiff from 'json-diff' @@ -78,7 +78,7 @@ async function runTest(dir: string, vstdir: string) { throw new Error(`Expected to throw error "${config.error}"`) } else { await fn() - const result = files.loadYAML(output) + const result = new Loader(output).raw() const expected = loadExpected({dir, file: config.expected}) const diff = jsonDiff.diffString(expected, result) @@ -108,11 +108,11 @@ export function getDefaultInputs(dir: string) { } export function loadExpected(data: {dir: string; file?: string}) { - if (check.isDefined(data.file)) return files.loadYAML(path.join(data.dir, data.file)) + if (check.isDefined(data.file)) return new Loader(path.join(data.dir, data.file)).raw() for (const name of ['est.yaml', 'expected.yaml']) { const file = path.join(data.dir, name) - if (files.isFile(file)) return files.loadYAML(file) + if (files.isFile(file)) return new Loader(file).raw() } throw new Error(`Did not find expected service template in directory "${data.dir}"`) diff --git a/src/enricher/elements.ts b/src/enricher/elements.ts index 0ccc1274d2..6db3a2411f 100644 --- a/src/enricher/elements.ts +++ b/src/enricher/elements.ts @@ -20,9 +20,8 @@ export class ElementEnricher { if (!utils.isEmpty(node.technologies)) continue for (const plugin of this.graph.plugins.technology) { - const assignments = plugin.assign(node) - for (const assignment of assignments) { - this.graph.addTechnology(node, assignment) + for (const map of plugin.assign(node)) { + this.graph.addTechnology(node, map) } } } diff --git a/src/graph/graph.ts b/src/graph/graph.ts index 0ef7af04ff..92105652ba 100644 --- a/src/graph/graph.ts +++ b/src/graph/graph.ts @@ -2,12 +2,13 @@ import * as assert from '#assert' import * as check from '#check' import Import from '#graph/import' import {Options} from '#graph/options' -import {ConditionalTechnologyAssignment, TechnologyPlugin} from '#graph/plugin' +import {TechnologyPlugin} from '#graph/plugin' import {Populator} from '#graph/populator' import Technology from '#graph/technology' import {andify, generatify, simplify} from '#graph/utils' import Normalizer from '#normalizer' import {ServiceTemplate, TOSCA_DEFINITIONS_VERSION} from '#spec/service-template' +import {TechnologyTemplateMap} from '#spec/technology-template' import { ArtifactPropertyPresenceArguments, GroupPropertyPresenceArguments, @@ -540,20 +541,22 @@ export default class Graph { this.serviceTemplate.topology_template.variability.constraints.push(constraint) } - addTechnology(node: Node, assignment: ConditionalTechnologyAssignment) { + addTechnology(node: Node, map: TechnologyTemplateMap) { if (check.isUndefined(node.raw.technology)) node.raw.technology = [] assert.isArray(node.raw.technology, `Technology of ${node.display} not normalized`) + const [technology, template] = utils.firstEntry(map) + // Normalize - assignment.conditions = check.isArray(assignment.conditions) - ? simplify(andify(assignment.conditions)) - : assignment.conditions + template.conditions = check.isArray(template.conditions) + ? simplify(andify(template.conditions)) + : template.conditions // Generatify - assignment.conditions = check.isDefined(assignment.conditions) ? generatify(assignment.conditions) : undefined + template.conditions = check.isDefined(template.conditions) ? generatify(template.conditions) : undefined node.raw.technology.push({ - [assignment.technology]: {conditions: assignment.conditions, weight: assignment.weight}, + [technology]: {conditions: template.conditions, weight: template.weight, assign: template.assign}, }) } diff --git a/src/graph/loader.ts b/src/graph/loader.ts index c35b91cad4..53618f7e57 100644 --- a/src/graph/loader.ts +++ b/src/graph/loader.ts @@ -20,8 +20,12 @@ export default class Loader { this.dir = files.getDirectory(file) } + raw() { + return files.loadYAML(this.file) + } + async load() { - this.serviceTemplate = files.loadYAML(this.file) + this.serviceTemplate = this.raw() /** * Load type-specific conditions @@ -43,7 +47,7 @@ export default class Loader { private async loadTypeSpecificConditions() { assert.isDefined(this.serviceTemplate, 'Template not loaded') - assert.isDefined(this.serviceTemplate.topology_template) + if (check.isUndefined(this.serviceTemplate.topology_template)) return let conditions = this.serviceTemplate.topology_template.variability?.type_specific_conditions @@ -51,7 +55,9 @@ export default class Loader { * Load rules from specified file */ if (check.isString(conditions)) { + console.log('going to load') conditions = files.loadYAML(path.join(this.dir, conditions)) + console.log(conditions) } /** @@ -72,7 +78,7 @@ export default class Loader { private async loadTechnologyRules() { assert.isDefined(this.serviceTemplate, 'Template not loaded') - assert.isDefined(this.serviceTemplate.topology_template) + if (check.isUndefined(this.serviceTemplate.topology_template)) return let rules = this.serviceTemplate.topology_template.variability?.technology_assignment_rules @@ -92,6 +98,15 @@ export default class Loader { } } + /** + * Load rules from other default file + */ + if (check.isUndefined(rules)) { + if (files.exists(path.join(this.dir, 'lib', 'rules.yaml'))) { + rules = files.loadYAML(path.join(this.dir, 'lib', 'rules.yaml')) + } + } + if (check.isUndefined(this.serviceTemplate.topology_template.variability)) this.serviceTemplate.topology_template.variability = {} this.serviceTemplate.topology_template.variability.technology_assignment_rules = rules @@ -99,7 +114,7 @@ export default class Loader { private async loadTechnologyPluginBuilders() { assert.isDefined(this.serviceTemplate, 'Template not loaded') - assert.isDefined(this.serviceTemplate.topology_template) + if (check.isUndefined(this.serviceTemplate.topology_template)) return if (check.isUndefined(this.serviceTemplate.topology_template.variability)) this.serviceTemplate.topology_template.variability = {} diff --git a/src/graph/plugin.ts b/src/graph/plugin.ts index 46166e5968..4f9ca9915a 100644 --- a/src/graph/plugin.ts +++ b/src/graph/plugin.ts @@ -2,21 +2,15 @@ import * as assert from '#assert' import * as check from '#check' import Graph from '#graph/graph' import Node from '#graph/node' -import {LogicExpression} from '#spec/variability' +import {TechnologyTemplateMap} from '#spec/technology-template' import * as utils from '#utils' -export type ConditionalTechnologyAssignment = { - technology: string - conditions?: LogicExpression | LogicExpression[] - weight?: number -} - export type TechnologyPluginBuilder = { build(graph: Graph): TechnologyPlugin } export type TechnologyPlugin = { - assign: (node: Node) => ConditionalTechnologyAssignment[] + assign: (node: Node) => TechnologyTemplateMap[] } export class TechnologyRulePluginBuilder implements TechnologyPluginBuilder { @@ -43,11 +37,11 @@ export class TechnologyRulePlugin implements TechnologyPlugin { return check.isDefined(this.getRules()) } - assign(node: Node): ConditionalTechnologyAssignment[] { - const assignments: ConditionalTechnologyAssignment[] = [] + assign(node: Node): TechnologyTemplateMap[] { + const maps: TechnologyTemplateMap[] = [] const map = this.getRules() - if (check.isUndefined(map)) return assignments + if (check.isUndefined(map)) return maps for (const technology of Object.keys(map)) { const rules = map[technology] @@ -57,22 +51,26 @@ export class TechnologyRulePlugin implements TechnologyPlugin { if (check.isDefined(rule.host)) { const hosts = node.hosts.filter(it => it.getType().name === rule.host) for (const host of hosts) { - assignments.push({ - technology, - conditions: utils.filterNotNull([{node_presence: host.name}, rule.conditions]), - weight: rule.weight, + maps.push({ + [technology]: { + conditions: utils.filterNotNull([{node_presence: host.name}, rule.conditions]), + weight: rule.weight, + assign: rule.assign, + }, }) } } else { - assignments.push({ - technology, - conditions: rule.conditions, - weight: rule.weight, + maps.push({ + [technology]: { + conditions: rule.conditions, + weight: rule.weight, + assign: rule.assign, + }, }) } } } - return assignments + return maps } } diff --git a/src/graph/technology.ts b/src/graph/technology.ts index fbe75253a9..9aba5cd9fa 100644 --- a/src/graph/technology.ts +++ b/src/graph/technology.ts @@ -13,6 +13,7 @@ export default class Technology extends Element { readonly index: number readonly container: Node readonly weight: number + readonly assign?: string readonly defaultAlternative: boolean @@ -24,6 +25,7 @@ export default class Technology extends Element { this.container = data.container this.index = data.index this.weight = data.raw.weight ?? 1 + this.assign = data.raw.assign this.conditions = check.isDefined(data.raw.default_alternative) ? [false] : utils.toList(data.raw.conditions) this.defaultAlternative = data.raw.default_alternative ?? false diff --git a/src/normalizer/index.ts b/src/normalizer/index.ts index 2df35437b8..c0b148d3c3 100644 --- a/src/normalizer/index.ts +++ b/src/normalizer/index.ts @@ -236,6 +236,7 @@ export default class Normalizer { if (check.isDefined(rule.host)) assert.isString(rule.host) if (check.isDefined(rule.conditions)) assert.isObject(rule.conditions) if (check.isDefined(rule.weight)) assert.isNumber(rule.weight) + if (check.isDefined(rule.assign)) assert.isString(rule.assign) } } } diff --git a/src/orchestrators/index.ts b/src/orchestrators/index.ts index e59d283d68..55c366d65d 100644 --- a/src/orchestrators/index.ts +++ b/src/orchestrators/index.ts @@ -48,7 +48,7 @@ export type OrchestratorOperationOptions = { time?: number } -export type OrchestratorValidateOptions = {inputs?: string} & OrchestratorOperationOptions +export type OrchestratorValidateOptions = {inputs?: string; dry?: boolean} & OrchestratorOperationOptions export interface Orchestrator { attest: () => Promise diff --git a/src/orchestrators/xopera.ts b/src/orchestrators/xopera.ts index 53239f2850..59d1ea9cbb 100644 --- a/src/orchestrators/xopera.ts +++ b/src/orchestrators/xopera.ts @@ -5,7 +5,12 @@ import {Shell} from '#shell' import std from '#std' import * as utils from '#utils' import _ from 'lodash' -import {NodeTemplateAttributesMap, Orchestrator, OrchestratorOperationOptions} from './index' +import { + NodeTemplateAttributesMap, + Orchestrator, + OrchestratorOperationOptions, + OrchestratorValidateOptions, +} from './index' export type xOperaConfig = (xOperaNativeConfig & {wsl: false}) | (xOperaWSLConfig & {wsl: true}) @@ -45,7 +50,7 @@ export class xOpera implements Orchestrator { await this.shell.execute([this.binary, '--version']) } - async validate(instance: Instance, options?: {inputs?: string} & OrchestratorOperationOptions) { + async validate(instance: Instance, options?: OrchestratorValidateOptions) { const command = [ this.binary, 'validate', @@ -58,6 +63,7 @@ export class xOpera implements Orchestrator { command.push('--inputs', this.shell.resolve(options.inputs)) if (options?.verbose) command.push('--verbose') + if (options?.dry) command.push('--executors') await this.shell.execute(command) } diff --git a/src/query/plugins/file.ts b/src/query/plugins/file.ts index 3f09faccfe..7db44c173b 100644 --- a/src/query/plugins/file.ts +++ b/src/query/plugins/file.ts @@ -1,12 +1,11 @@ -import * as files from '#files' -import {ServiceTemplate} from '#spec/service-template' +import Loader from '#graph/loader' import {TemplatesRepository} from './index' export class FileTemplateRepository implements TemplatesRepository { async getTemplate(name: string) { return { name, - template: files.loadYAML(name), + template: new Loader(name).raw(), } } diff --git a/src/query/plugins/winery.ts b/src/query/plugins/winery.ts index 21959aebff..d4e755a9f6 100644 --- a/src/query/plugins/winery.ts +++ b/src/query/plugins/winery.ts @@ -1,5 +1,5 @@ import * as files from '#files' -import {ServiceTemplate} from '#spec/service-template' +import Loader from '#graph/loader' import glob from 'glob' import os from 'os' import path from 'path' @@ -24,7 +24,7 @@ export class WineryTemplatesRepository implements TemplatesRepository { // use glob to recursively search all files named 'ServiceTemplate.tosca' within the repo return glob.sync(searchPattern).map(v => ({ name: v.split('/')[v.split('/').length - 2], - template: files.loadYAML(v), + template: new Loader(v).raw(), })) } @@ -33,7 +33,7 @@ export class WineryTemplatesRepository implements TemplatesRepository { * @param name The name of the template */ async getTemplate(name: string) { - return {name, template: files.loadYAML(this.getTemplatePath(name))} + return {name, template: new Loader(this.getTemplatePath(name)).raw()} } getTemplatePath(name: string) { diff --git a/src/repositories/instances.ts b/src/repositories/instances.ts index 0cc73748a2..ba7091379e 100644 --- a/src/repositories/instances.ts +++ b/src/repositories/instances.ts @@ -1,5 +1,6 @@ import * as check from '#check' import * as files from '#files' +import Loader from '#graph/loader' import orchestrators from '#orchestrators' import {ServiceTemplate} from '#spec/service-template' import {InputAssignmentMap} from '#spec/topology-template' @@ -182,7 +183,7 @@ export class Instance { } loadServiceTemplate() { - return files.loadYAML(this.getServiceTemplate()) + return new Loader(this.getServiceTemplate()).raw() } setServiceTemplate(template: ServiceTemplate, time: number) { @@ -193,8 +194,12 @@ export class Instance { return path.join(this.getTemplateDirectory(), 'variable-service-template.yaml') } - loadVariableServiceTemplate() { - return files.loadYAML(this.getVariableServiceTemplate()) + async loadVariableServiceTemplate() { + return await new Loader(this.getVariableServiceTemplate()).load() + } + + loadRawVariableServiceTemplate() { + return new Loader(this.getVariableServiceTemplate()).raw() } hasVariabilityInputs() { diff --git a/src/repositories/templates.ts b/src/repositories/templates.ts index 20fc55dedd..8bd67186d5 100644 --- a/src/repositories/templates.ts +++ b/src/repositories/templates.ts @@ -3,8 +3,8 @@ import Controller from '#controller' import * as crypto from '#crypto' import * as files from '#files' import * as git from '#git' +import Loader from '#graph/loader' import {Asset} from '#repositories/assets' -import {ServiceTemplate} from '#spec/service-template' import * as utils from '#utils' import env from '#utils/env' import path from 'path' @@ -104,7 +104,7 @@ export class Template { } loadVariableServiceTemplate() { - return files.loadYAML(this.getVariableServiceTemplatePath()) + return new Loader(this.getVariableServiceTemplatePath()).raw() } delete() { diff --git a/src/resolver/index.ts b/src/resolver/index.ts index 44bb135251..4cd573cfa1 100644 --- a/src/resolver/index.ts +++ b/src/resolver/index.ts @@ -1,8 +1,8 @@ import * as assert from '#assert' import * as check from '#check' import Enricher from '#enricher' -import * as files from '#files' import Graph from '#graph/graph' +import Loader from '#graph/loader' import Inputs from '#resolver/inputs' import Resolver from '#resolver/resolver' import {ServiceTemplate} from '#spec/service-template' @@ -27,7 +27,8 @@ export async function run(options: ResolveOptions): Promise { /** * Service template */ - if (check.isString(options.template)) options.template = files.loadYAML(options.template) + // TODO: where to load? inside enricher? + if (check.isString(options.template)) options.template = await new Loader(options.template).load() /** * Enricher diff --git a/src/resolver/optimizer.ts b/src/resolver/optimizer.ts index a2a1f6d990..43a2a25a39 100644 --- a/src/resolver/optimizer.ts +++ b/src/resolver/optimizer.ts @@ -4,6 +4,7 @@ import {Result} from '#resolver/result' export default class Optimizer { private readonly graph: Graph private results: Result[] + private transformed = false constructor(graph: Graph, results: Result[]) { this.graph = graph @@ -11,6 +12,15 @@ export default class Optimizer { } run() { + this.optimize() + + return this.first() + } + + optimize() { + if (this.transformed) return this.results + this.transformed = true + /** * Optimize topology */ @@ -31,7 +41,7 @@ export default class Optimizer { */ if (this.graph.options.solver.technologies.unique) this.ensureTechnologiesUniqueness() - return this.first() + return this.results } private optimizeTopology() { @@ -92,7 +102,10 @@ export default class Optimizer { private ensureTechnologiesUniqueness() { if (this.results.length > 1) { if (this.graph.options.solver.technologies.optimize) { - if (this.first().technologies.count === this.second().technologies.count) + if ( + this.first().technologies[this.graph.options.solver.technologies.mode] === + this.second().technologies[this.graph.options.solver.technologies.mode] + ) throw new Error(`The result is ambiguous considering technologies (besides optimization)`) } else { throw new Error(`The result is ambiguous considering technologies (without optimization)`) diff --git a/src/resolver/result.ts b/src/resolver/result.ts index 9dec27a626..31b52896d6 100644 --- a/src/resolver/result.ts +++ b/src/resolver/result.ts @@ -34,25 +34,34 @@ export class Result { } private weightTopology() { + let count = 0 let weight = 0 - for (const node of this.graph.nodes) { - if (check.isTrue(this.map[node.id])) weight += node.weight + for (const node of this.graph.nodes.filter(it => this.isPresent(it))) { + count++ + weight += node.weight } - return {count: this.graph.nodes.length, weight} + return {count, weight} } private weightTechnologies() { const weights: {[key: string]: number} = {} - for (const technology of this.graph.technologies) { + for (const technology of this.graph.technologies.filter(it => this.isPresent(it))) { if (check.isUndefined(weights[technology.name])) weights[technology.name] = 0 - if (check.isTrue(this.map[technology.id])) weights[technology.name] += technology.weight + weights[technology.name] += technology.weight } return { - count: Object.values(weights).filter(it => it !== 0).length, + count: Object.values(weights).length, weight: utils.sum(Object.values(weights)), } } + /** + * Can not use element.present yet since we are currently selecting the result! + */ + isPresent(element: Element) { + return check.isTrue(this.map[element.id]) + } + equals(result: Result): boolean { if (Object.keys(this.map).length !== Object.keys(result.map).length) return false diff --git a/src/resolver/transformer.ts b/src/resolver/transformer.ts index b2f9a2cf60..0a565101bb 100644 --- a/src/resolver/transformer.ts +++ b/src/resolver/transformer.ts @@ -233,12 +233,29 @@ export default class Transformer { } private transformTechnology(element: Node, template: NodeTemplate) { + assert.isString(template.type) + // Ignore if previously had no technologies if (utils.isEmpty(element.technologies)) return const technology = element.technologies.find(it => it.present) if (check.isUndefined(technology)) throw new Error(`${element.Display} has no present technology`) - template.type += '.' + technology.name + + if (check.isDefined(technology.assign)) { + template.type = technology.assign + } else { + let type = template.type + type += '.' + technology.name + + const host = element.hosts.find(it => it.present) + if (check.isDefined(host)) { + type += '.' + host.getType().name.split('.')[0] + } else { + type += '.' + template.type.split('.')[0] + } + + template.type = type + } } private transformProperties( diff --git a/src/specification/technology-template.ts b/src/specification/technology-template.ts index 559784c1c1..6debf38bf9 100644 --- a/src/specification/technology-template.ts +++ b/src/specification/technology-template.ts @@ -7,9 +7,12 @@ import { export type TechnologyAssignment = string | VariabilityPointList +export type TechnologyTemplateMap = {[technology: string]: TechnologyTemplate} + export type TechnologyTemplate = VariabilityAlternative & { default_condition_mode?: TechnologyDefaultConditionMode weight?: number + assign?: string } export type TechnologyAssignmentRulesMap = {[technology: string]: TechnologyAssignmentRule[]} @@ -19,4 +22,5 @@ export type TechnologyAssignmentRule = { host?: string conditions?: LogicExpression | LogicExpression[] weight?: number + assign?: string } diff --git a/src/utils/files.ts b/src/utils/files.ts index ae1fec1c20..c2df9ffbe6 100644 --- a/src/utils/files.ts +++ b/src/utils/files.ts @@ -4,10 +4,11 @@ import archiver from 'archiver' import axios from 'axios' import * as ejs from 'ejs' import extract from 'extract-zip' -import * as fs from 'fs' +import * as fss from 'fs' import * as fse from 'fs-extra' import Glob from 'glob' import * as yaml from 'js-yaml' +import lnk from 'lnk' import _ from 'lodash' import os from 'os' import * as path from 'path' @@ -21,7 +22,7 @@ export const SCRIPTS_DIR = path.resolve(ASSETS_DIR, 'scripts') export const TMP_PREFIX = 'opentosca-vintner--' export function exists(file: string) { - return fs.existsSync(file) + return fss.existsSync(file) } export function assertFile(file: string) { @@ -38,7 +39,7 @@ export function assertDirectory(dir: string, file = false) { export function isEmpty(dir: string) { const resolved = path.resolve(dir) - return fs.readdirSync(resolved).length === 0 + return fss.readdirSync(resolved).length === 0 } export function assertEmpty(dir: string) { @@ -47,21 +48,21 @@ export function assertEmpty(dir: string) { } export function isFile(path: string) { - return exists(path) && fs.lstatSync(path).isFile() + return exists(path) && fss.lstatSync(path).isFile() } export function isDirectory(path: string) { - return exists(path) && fs.lstatSync(path).isDirectory() + return exists(path) && fss.lstatSync(path).isDirectory() } export function getSize(file: string) { assertFile(file) - return fs.lstatSync(file).size + return fss.lstatSync(file).size } export function countLines(file: string) { assertFile(file) - return fs.readFileSync(path.resolve(file), 'utf-8').split(/\r?\n/).length + return fss.readFileSync(path.resolve(file), 'utf-8').split(/\r?\n/).length } export function isLink(path: string) { @@ -70,7 +71,7 @@ export function isLink(path: string) { export function loadFile(file: string) { assertFile(file) - return fs.readFileSync(path.resolve(file), 'utf-8') + return fss.readFileSync(path.resolve(file), 'utf-8') } export function loadYAML(file: string) { @@ -87,22 +88,22 @@ export function storeFile(file: string, data: string, options?: {onlyIfChanged?: } } - fs.writeFileSync(path.resolve(file), data) + fss.writeFileSync(path.resolve(file), data) return file } export function storeYAML(file: string, data: any | string) { - fs.writeFileSync(path.resolve(file), check.isString(data) ? data : toYAML(data)) + fss.writeFileSync(path.resolve(file), check.isString(data) ? data : toYAML(data)) return file } export function storeJSON(file: string, data: any | string) { - fs.writeFileSync(path.resolve(file), check.isString(data) ? data : toJSON(data)) + fss.writeFileSync(path.resolve(file), check.isString(data) ? data : toJSON(data)) return file } export function storeENV(file: string, data: any | string) { - fs.writeFileSync(path.resolve(file), check.isString(data) ? data : toENV(data)) + fss.writeFileSync(path.resolve(file), check.isString(data) ? data : toENV(data)) return file } @@ -147,15 +148,24 @@ export async function sync(source: string, target: string) { }) } +export async function link(source: string, target: string) { + try { + await lnk(source, target, {force: true}) + } catch (e) { + if ((e.message || '').includes('are the same')) return + throw e + } +} + export function listDirectories(directory: string): string[] { - return fs + return fss .readdirSync(directory, {withFileTypes: true}) .filter(dirent => dirent.isDirectory()) .map(dirent => dirent.name.toString()) } export function listFiles(directory: string): string[] { - return fs + return fss .readdirSync(directory, {withFileTypes: true}) .filter(dirent => dirent.isFile()) .map(dirent => dirent.name.toString()) @@ -163,8 +173,8 @@ export function listFiles(directory: string): string[] { export function createDirectory(directory: string) { const resolved = path.resolve(directory) - if (!fs.existsSync(resolved)) { - fs.mkdirSync(resolved, {recursive: true}) + if (!fss.existsSync(resolved)) { + fss.mkdirSync(resolved, {recursive: true}) } } @@ -174,11 +184,11 @@ export function deleteDirectory(directory: string) { if (['/', '/etc', '/c', '/mnt', '/mnt/c', 'C:\\Windows\\system32', 'C:\\'].includes(resolved)) throw new Error(`Deleting directory "${resolved}" not allowed`) - fs.rmSync(resolved, {recursive: true, force: true}) + fss.rmSync(resolved, {recursive: true, force: true}) } export async function deleteFile(file: string) { - fs.unlinkSync(path.resolve(file)) + fss.unlinkSync(path.resolve(file)) } export function getDirectory(file: string) { @@ -202,7 +212,7 @@ export async function createArchive(source: string, target: string) { assertDirectory(target, true) return new Promise((resolve, reject) => { const archive = archiver('zip', {zlib: {level: 9}}) - const stream = fs.createWriteStream(target) + const stream = fss.createWriteStream(target) archive .directory(source, false) @@ -221,7 +231,7 @@ export async function download(source: string, target: string = temporary()): Pr responseType: 'stream', }) .then(response => { - const file = fs.createWriteStream(target) + const file = fss.createWriteStream(target) response.data.pipe(file) file.on('error', error => { file.close() @@ -251,7 +261,7 @@ export async function renderFile(source: string, data: ejs.Data, target?: string } export function stat(file: string) { - return fs.statSync(file) + return fss.statSync(file) } export async function glob(pattern: string | string[], options?: Glob.GlobOptionsWithFileTypesUnset) { diff --git a/tests/benchmark/test.ts b/tests/benchmark/test.ts index 4a18baa474..27f623980f 100644 --- a/tests/benchmark/test.ts +++ b/tests/benchmark/test.ts @@ -1,6 +1,5 @@ import benchmark, {generateBenchmarkServiceTemplate} from '#controller/setup/benchmark' -import * as files from '#files' -import {ServiceTemplate} from '#spec/service-template' +import Loader from '#graph/loader' import {expect} from 'chai' import * as path from 'path' @@ -11,6 +10,6 @@ describe('benchmark', () => { it('generate service template', () => { const result = generateBenchmarkServiceTemplate(2) - expect(result).to.deep.equal(files.loadYAML(path.join(__dirname, 'expected.yaml'))) + expect(result).to.deep.equal(new Loader(path.join(__dirname, 'expected.yaml')).raw()) }) }) diff --git a/tests/conformance/technologies/ambiguous-disabled/expected.yaml b/tests/conformance/technologies/ambiguous-disabled/expected.yaml index 2ae6dedc34..939f702c93 100644 --- a/tests/conformance/technologies/ambiguous-disabled/expected.yaml +++ b/tests/conformance/technologies/ambiguous-disabled/expected.yaml @@ -3,4 +3,4 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.ansible + type: container.ansible.container diff --git a/tests/conformance/technologies/conditional/expected.yaml b/tests/conformance/technologies/conditional/expected.yaml index 2ae6dedc34..939f702c93 100644 --- a/tests/conformance/technologies/conditional/expected.yaml +++ b/tests/conformance/technologies/conditional/expected.yaml @@ -3,4 +3,4 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.ansible + type: container.ansible.container diff --git a/tests/conformance/technologies/default-true/expected.yaml b/tests/conformance/technologies/default-true/expected.yaml index e099028194..5c0bccdb24 100644 --- a/tests/conformance/technologies/default-true/expected.yaml +++ b/tests/conformance/technologies/default-true/expected.yaml @@ -3,4 +3,4 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.terraform + type: container.terraform.container diff --git a/tests/conformance/technologies/lowercase/expected.yaml b/tests/conformance/technologies/lowercase/expected.yaml index 2ae6dedc34..939f702c93 100644 --- a/tests/conformance/technologies/lowercase/expected.yaml +++ b/tests/conformance/technologies/lowercase/expected.yaml @@ -3,4 +3,4 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.ansible + type: container.ansible.container diff --git a/tests/conformance/technologies/optimization-double/expected.yaml b/tests/conformance/technologies/optimization-double/expected.yaml index 9065a855c0..284aab291b 100644 --- a/tests/conformance/technologies/optimization-double/expected.yaml +++ b/tests/conformance/technologies/optimization-double/expected.yaml @@ -3,7 +3,7 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.ansible + type: container.ansible.container another: - type: another.ansible + type: another.ansible.another diff --git a/tests/conformance/technologies/optimization-order/expected.yaml b/tests/conformance/technologies/optimization-order/expected.yaml index 9065a855c0..284aab291b 100644 --- a/tests/conformance/technologies/optimization-order/expected.yaml +++ b/tests/conformance/technologies/optimization-order/expected.yaml @@ -3,7 +3,7 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.ansible + type: container.ansible.container another: - type: another.ansible + type: another.ansible.another diff --git a/tests/conformance/technologies/optimization-weight/expected.yaml b/tests/conformance/technologies/optimization-weight/expected.yaml index dd8fdd603d..a6e8ae5169 100644 --- a/tests/conformance/technologies/optimization-weight/expected.yaml +++ b/tests/conformance/technologies/optimization-weight/expected.yaml @@ -3,7 +3,7 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.terraform + type: container.terraform.container another: - type: another.ansible + type: another.ansible.another diff --git a/tests/conformance/technologies/optimization/expected.yaml b/tests/conformance/technologies/optimization/expected.yaml index 9065a855c0..284aab291b 100644 --- a/tests/conformance/technologies/optimization/expected.yaml +++ b/tests/conformance/technologies/optimization/expected.yaml @@ -3,7 +3,7 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.ansible + type: container.ansible.container another: - type: another.ansible + type: another.ansible.another diff --git a/tests/conformance/technologies/rules/expected.yaml b/tests/conformance/technologies/rules/expected.yaml index 18eac326c3..f19c763bd7 100644 --- a/tests/conformance/technologies/rules/expected.yaml +++ b/tests/conformance/technologies/rules/expected.yaml @@ -3,7 +3,7 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: application: - type: application.terraform + type: application.terraform.ansible_terraform_host requirements: - host: ansible_terraform_host - database: database @@ -12,9 +12,9 @@ topology_template: type: ansible_terraform_host database: - type: database.terraform + type: database.terraform.dbms requirements: - host: dbms dbms: - type: dbms.terraform + type: dbms.terraform.dbms diff --git a/tests/conformance/technologies/unique-disabled/expected.yaml b/tests/conformance/technologies/unique-disabled/expected.yaml index 351c8626a2..845685af7c 100644 --- a/tests/conformance/technologies/unique-disabled/expected.yaml +++ b/tests/conformance/technologies/unique-disabled/expected.yaml @@ -3,4 +3,4 @@ tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: container: - type: container.puppet + type: container.puppet.container diff --git a/tests/enricher/technology-plugin-loader-default/plugins/technology/terraform/index.js b/tests/enricher/technology-plugin-loader-default/plugins/technology/terraform/index.js index bb71760f1d..4997c8bccb 100644 --- a/tests/enricher/technology-plugin-loader-default/plugins/technology/terraform/index.js +++ b/tests/enricher/technology-plugin-loader-default/plugins/technology/terraform/index.js @@ -1,14 +1,12 @@ /* eslint-disable */ -const technology = require('technology') +const technology = require("technology"); module.exports = { build: (graph) => { return { assign: (node) => { - return [{ - technology: technology.name() - }]; + return [{ [technology.name()]: {} }]; } }; } diff --git a/tests/enricher/technology-plugin-loader-file/plugin/index.js b/tests/enricher/technology-plugin-loader-file/plugin/index.js index bb71760f1d..4997c8bccb 100644 --- a/tests/enricher/technology-plugin-loader-file/plugin/index.js +++ b/tests/enricher/technology-plugin-loader-file/plugin/index.js @@ -1,14 +1,12 @@ /* eslint-disable */ -const technology = require('technology') +const technology = require("technology"); module.exports = { build: (graph) => { return { assign: (node) => { - return [{ - technology: technology.name() - }]; + return [{ [technology.name()]: {} }]; } }; } diff --git a/tests/integration/adaptation.test.ts b/tests/integration/adaptation.test.ts index daf85ded52..6d03664cc9 100644 --- a/tests/integration/adaptation.test.ts +++ b/tests/integration/adaptation.test.ts @@ -1,6 +1,5 @@ -import * as files from '#files' +import Loader from '#graph/loader' import {Instance} from '#repositories/instances' -import {ServiceTemplate} from '#spec/service-template' import std from '#std' import * as utils from '#utils' import {expect} from 'chai' @@ -21,12 +20,8 @@ if (!integrationTestsEnabled) { // Import template const template = 'xopera-getting-started-template' const templateDirectory = path.join(examplesDir, 'xopera-getting-started') - const firstTemplate = files.loadYAML( - path.join(templateDirectory, 'tests', 'first', 'expected.yaml') - ) - const secondTemplate = files.loadYAML( - path.join(templateDirectory, 'tests', 'second', 'expected.yaml') - ) + const firstTemplate = new Loader(path.join(templateDirectory, 'tests', 'first', 'expected.yaml')).raw() + const secondTemplate = new Loader(path.join(templateDirectory, 'tests', 'second', 'expected.yaml')).raw() await Controller.templates.import({ template, diff --git a/tests/integration/swap.test.ts b/tests/integration/swap.test.ts index 65605d811f..4311bed968 100644 --- a/tests/integration/swap.test.ts +++ b/tests/integration/swap.test.ts @@ -1,7 +1,6 @@ import Controller from '#controller' -import * as files from '#files' +import Loader from '#graph/loader' import {Instance} from '#repositories/instances' -import {ServiceTemplate} from '#spec/service-template' import std from '#std' import {expect} from 'chai' import path from 'path' @@ -20,9 +19,7 @@ if (!integrationTestsEnabled) { // Alpha Template const alphaName = 'xopera-test-swap-template-alpha' const alphaDirectoy = path.join(examplesDir, alphaName) - const alphaTemplate = files.loadYAML( - path.join(alphaDirectoy, 'variable-service-template.yaml') - ) + const alphaTemplate = new Loader(path.join(alphaDirectoy, 'variable-service-template.yaml')).raw() await Controller.templates.import({ template: alphaName, path: alphaDirectoy, @@ -31,9 +28,7 @@ if (!integrationTestsEnabled) { // Bravo Template const bravoName = 'xopera-test-swap-template-bravo' const bravoDirectoy = path.join(examplesDir, bravoName) - const bravoTemplate = files.loadYAML( - path.join(bravoDirectoy, 'variable-service-template.yaml') - ) + const bravoTemplate = new Loader(path.join(bravoDirectoy, 'variable-service-template.yaml')).raw() await Controller.templates.import({ template: bravoName, path: bravoDirectoy, @@ -48,7 +43,7 @@ if (!integrationTestsEnabled) { }) // Expect that initial vst matches alpha - expect(instance.loadVariableServiceTemplate()).to.deep.equal(alphaTemplate) + expect(instance.loadRawVariableServiceTemplate()).to.deep.equal(alphaTemplate) // Check that can be deployed await Controller.instances.resolve({instance: instanceName}) @@ -62,7 +57,7 @@ if (!integrationTestsEnabled) { }) // Expect that new vst matches bravo - expect(instance.loadVariableServiceTemplate()).to.deep.equal(bravoTemplate) + expect(instance.loadRawVariableServiceTemplate()).to.deep.equal(bravoTemplate) // Check that instance can be updated await Controller.instances.resolve({instance: instanceName}) diff --git a/tests/utils.ts b/tests/utils.ts index efdd723c29..b935d4099c 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -7,7 +7,7 @@ import { loadExpected, } from '#controller/template/test' import * as files from '#files' -import {ServiceTemplate} from '#spec/service-template' +import Loader from '#graph/loader' import std from '#std' import {toList} from '#utils/utils' import {expect} from 'chai' @@ -78,7 +78,7 @@ export function getDefaultTest(dir: string, vstdir?: string) { await expectAsyncThrow(fn, config.error) } else { await fn() - const result = files.loadYAML(output) + const result = new Loader(output).raw() const expected = loadExpected({dir, file: config.expected}) expect(result).to.deep.equal(expected) } diff --git a/yarn.lock b/yarn.lock index 2742b9cdb8..81b0355914 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4445,6 +4445,18 @@ __metadata: languageName: node linkType: hard +"lnk@npm:^1.1.0": + version: 1.1.0 + resolution: "lnk@npm:1.1.0" + dependencies: + arrify: ^1.0.1 + mkdirp: ^0.5.0 + pify: ^2.3 + rimraf: ^2.5.4 + checksum: e9946b8d55a4bc69ed6c160c2dafc275da0de3a06d272a39669e01c69ad4a98db9677806cc6103fa1d5fc11c41dcf9248f00a5573a3e1b8a537180cc1bb9e155 + languageName: node + linkType: hard + "locate-path@npm:^5.0.0": version: 5.0.0 resolution: "locate-path@npm:5.0.0" @@ -4920,7 +4932,7 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^0.5.1": +"mkdirp@npm:^0.5.0, mkdirp@npm:^0.5.1": version: 0.5.6 resolution: "mkdirp@npm:0.5.6" dependencies: @@ -5468,6 +5480,7 @@ __metadata: js-yaml: ^4.1.0 json-diff: ^1.0.3 license-checker: ^25.0.1 + lnk: ^1.1.0 lodash: ^4.17.21 logic-solver: ^2.0.1 mocha: ^10.2.0 @@ -5806,6 +5819,13 @@ __metadata: languageName: node linkType: hard +"pify@npm:^2.3": + version: 2.3.0 + resolution: "pify@npm:2.3.0" + checksum: 9503aaeaf4577acc58642ad1d25c45c6d90288596238fb68f82811c08104c800e5a7870398e9f015d82b44ecbcbef3dc3d4251a1cbb582f6e5959fe09884b2ba + languageName: node + linkType: hard + "pkg-dir@npm:^4.1.0": version: 4.2.0 resolution: "pkg-dir@npm:4.2.0" @@ -6306,7 +6326,7 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^2.6.3": +"rimraf@npm:^2.5.4, rimraf@npm:^2.6.3": version: 2.7.1 resolution: "rimraf@npm:2.7.1" dependencies: