From dcf292836eb8f217149a56dfda9a4d0d3195977f Mon Sep 17 00:00:00 2001 From: Simone Rodigari <32323373+SRodi@users.noreply.github.com> Date: Tue, 28 Jan 2025 14:17:13 +0000 Subject: [PATCH] test(mc): initial multicloud IaC boilerplate GKE, AKS, Kind (#1268) # Description Initial work on multi-cloud * create modules for aks, gke, kind and retina * use gcloud, azure, kind and helm providers * create examples on how to use each module * create automated tests in Go Terratest for each module example (only initial work, since we require creds for public clouds) * create integration test retina-kind (this can also be used as an example for AKS, GKE and eventually EKS) * create a Makefile for this subproject * create GH workflow with automated tests ![diagram](https://github.com/user-attachments/assets/38ded8ec-0c31-4e5d-9bd0-8729115cf5b3) ## Related Issue #1267 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/contributing). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed All modules were tested and work as expected. ![Screenshot 2025-01-24 at 12 18 55](https://github.com/user-attachments/assets/2d222a13-2b12-4a11-a001-1b03a254e152) See automated tests here https://github.com/microsoft/retina/actions/runs/12993893617/job/36237118572 ![image](https://github.com/user-attachments/assets/edafa98b-1d5d-44b0-a393-1bf7b7b70bda) ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --- .github/workflows/test-multicloud.yml | 31 + test/multicloud/.gitignore | 6 + test/multicloud/Makefile | 42 + test/multicloud/README.md | 98 + test/multicloud/diagrams/diagram.excalidraw | 3366 +++++++++++++++++ test/multicloud/diagrams/diagram.svg | 2 + .../examples/aks/.terraform.lock.hcl | 20 + test/multicloud/examples/aks/main.tf | 12 + test/multicloud/examples/aks/providers.tf | 20 + test/multicloud/examples/aks/variables.tf | 33 + .../examples/gke/.terraform.lock.hcl | 20 + test/multicloud/examples/gke/main.tf | 9 + test/multicloud/examples/gke/outputs.tf | 14 + test/multicloud/examples/gke/providers.tf | 15 + test/multicloud/examples/gke/variables.tf | 19 + .../retina-kind/.terraform.lock.hcl | 34 + .../examples/integration/retina-kind/main.tf | 10 + .../integration/retina-kind/outputs.tf | 19 + .../integration/retina-kind/providers.tf | 26 + .../retina-kind/test-integration-kind-config | 3 + .../integration/retina-kind/test-kind-config | 3 + .../integration/retina-kind/variables.tf | 11 + .../examples/kind/.terraform.lock.hcl | 16 + test/multicloud/examples/kind/main.tf | 4 + test/multicloud/examples/kind/outputs.tf | 19 + test/multicloud/examples/kind/providers.tf | 12 + test/multicloud/examples/kind/variables.tf | 4 + .../live/retina-aks/.terraform.lock.hcl | 40 + test/multicloud/live/retina-aks/main.tf | 16 + test/multicloud/live/retina-aks/providers.tf | 34 + test/multicloud/live/retina-aks/variables.tf | 35 + .../live/retina-gke/.terraform.lock.hcl | 40 + test/multicloud/live/retina-gke/main.tf | 12 + test/multicloud/live/retina-gke/outputs.tf | 3 + test/multicloud/live/retina-gke/providers.tf | 30 + test/multicloud/live/retina-gke/variables.tf | 23 + .../live/retina-kind/.terraform.lock.hcl | 36 + test/multicloud/live/retina-kind/main.tf | 9 + test/multicloud/live/retina-kind/providers.tf | 26 + test/multicloud/live/retina-kind/variables.tf | 5 + test/multicloud/modules/aks/main.tf | 47 + test/multicloud/modules/aks/outputs.tf | 24 + test/multicloud/modules/aks/provider.tf | 9 + test/multicloud/modules/aks/variables.tf | 78 + test/multicloud/modules/gke/main.tf | 34 + test/multicloud/modules/gke/output.tf | 14 + test/multicloud/modules/gke/provider.tf | 9 + test/multicloud/modules/gke/variables.tf | 19 + test/multicloud/modules/kind/main.tf | 20 + test/multicloud/modules/kind/output.tf | 24 + test/multicloud/modules/kind/provider.tf | 9 + test/multicloud/modules/kind/variables.tf | 4 + test/multicloud/modules/retina/main.tf | 15 + test/multicloud/modules/retina/provider.tf | 8 + test/multicloud/modules/retina/variables.tf | 27 + test/multicloud/test/example_aks_test.go | 38 + test/multicloud/test/example_gke_test.go | 54 + test/multicloud/test/example_kind_test.go | 43 + test/multicloud/test/go.mod | 73 + test/multicloud/test/go.sum | 192 + .../test/integration_retina_kind_test.go | 49 + test/multicloud/test/testUtils.go | 120 + 62 files changed, 5087 insertions(+) create mode 100644 .github/workflows/test-multicloud.yml create mode 100644 test/multicloud/.gitignore create mode 100644 test/multicloud/Makefile create mode 100644 test/multicloud/README.md create mode 100644 test/multicloud/diagrams/diagram.excalidraw create mode 100644 test/multicloud/diagrams/diagram.svg create mode 100644 test/multicloud/examples/aks/.terraform.lock.hcl create mode 100644 test/multicloud/examples/aks/main.tf create mode 100644 test/multicloud/examples/aks/providers.tf create mode 100644 test/multicloud/examples/aks/variables.tf create mode 100644 test/multicloud/examples/gke/.terraform.lock.hcl create mode 100644 test/multicloud/examples/gke/main.tf create mode 100644 test/multicloud/examples/gke/outputs.tf create mode 100644 test/multicloud/examples/gke/providers.tf create mode 100644 test/multicloud/examples/gke/variables.tf create mode 100644 test/multicloud/examples/integration/retina-kind/.terraform.lock.hcl create mode 100644 test/multicloud/examples/integration/retina-kind/main.tf create mode 100644 test/multicloud/examples/integration/retina-kind/outputs.tf create mode 100644 test/multicloud/examples/integration/retina-kind/providers.tf create mode 100644 test/multicloud/examples/integration/retina-kind/test-integration-kind-config create mode 100644 test/multicloud/examples/integration/retina-kind/test-kind-config create mode 100644 test/multicloud/examples/integration/retina-kind/variables.tf create mode 100644 test/multicloud/examples/kind/.terraform.lock.hcl create mode 100644 test/multicloud/examples/kind/main.tf create mode 100644 test/multicloud/examples/kind/outputs.tf create mode 100644 test/multicloud/examples/kind/providers.tf create mode 100644 test/multicloud/examples/kind/variables.tf create mode 100644 test/multicloud/live/retina-aks/.terraform.lock.hcl create mode 100644 test/multicloud/live/retina-aks/main.tf create mode 100644 test/multicloud/live/retina-aks/providers.tf create mode 100644 test/multicloud/live/retina-aks/variables.tf create mode 100644 test/multicloud/live/retina-gke/.terraform.lock.hcl create mode 100644 test/multicloud/live/retina-gke/main.tf create mode 100644 test/multicloud/live/retina-gke/outputs.tf create mode 100644 test/multicloud/live/retina-gke/providers.tf create mode 100644 test/multicloud/live/retina-gke/variables.tf create mode 100644 test/multicloud/live/retina-kind/.terraform.lock.hcl create mode 100644 test/multicloud/live/retina-kind/main.tf create mode 100644 test/multicloud/live/retina-kind/providers.tf create mode 100644 test/multicloud/live/retina-kind/variables.tf create mode 100644 test/multicloud/modules/aks/main.tf create mode 100644 test/multicloud/modules/aks/outputs.tf create mode 100644 test/multicloud/modules/aks/provider.tf create mode 100644 test/multicloud/modules/aks/variables.tf create mode 100644 test/multicloud/modules/gke/main.tf create mode 100644 test/multicloud/modules/gke/output.tf create mode 100644 test/multicloud/modules/gke/provider.tf create mode 100644 test/multicloud/modules/gke/variables.tf create mode 100644 test/multicloud/modules/kind/main.tf create mode 100644 test/multicloud/modules/kind/output.tf create mode 100644 test/multicloud/modules/kind/provider.tf create mode 100644 test/multicloud/modules/kind/variables.tf create mode 100644 test/multicloud/modules/retina/main.tf create mode 100644 test/multicloud/modules/retina/provider.tf create mode 100644 test/multicloud/modules/retina/variables.tf create mode 100644 test/multicloud/test/example_aks_test.go create mode 100644 test/multicloud/test/example_gke_test.go create mode 100644 test/multicloud/test/example_kind_test.go create mode 100644 test/multicloud/test/go.mod create mode 100644 test/multicloud/test/go.sum create mode 100644 test/multicloud/test/integration_retina_kind_test.go create mode 100644 test/multicloud/test/testUtils.go diff --git a/.github/workflows/test-multicloud.yml b/.github/workflows/test-multicloud.yml new file mode 100644 index 0000000000..6281341efb --- /dev/null +++ b/.github/workflows/test-multicloud.yml @@ -0,0 +1,31 @@ +name: Test Multicloud + +on: + pull_request: + paths: + - 'test/multicloud/**' + +jobs: + multicloud-test: + runs-on: ubuntu-latest + + steps: + - uses: opentofu/setup-opentofu@v1 + with: + tofu_version: 1.8.3 + + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: '1.23' + + - name: Install dependencies + run: go mod download + working-directory: test/multicloud/ + + - name: Run tests + run: make test + working-directory: test/multicloud/ \ No newline at end of file diff --git a/test/multicloud/.gitignore b/test/multicloud/.gitignore new file mode 100644 index 0000000000..6f829cf6f9 --- /dev/null +++ b/test/multicloud/.gitignore @@ -0,0 +1,6 @@ +terraform.tfvars +.terraform +terraform.tfstate +*terraform.tfstate.* +service-key.json +*-kind-config diff --git a/test/multicloud/Makefile b/test/multicloud/Makefile new file mode 100644 index 0000000000..715e86ec2f --- /dev/null +++ b/test/multicloud/Makefile @@ -0,0 +1,42 @@ +PREFIX ?= retina +STACK_NAME ?= $(PREFIX)-aks + +.PHONY: init plan apply quick gke aks kind destroy clean kind-kubeconfig test + +plan: + cd live/$(STACK_NAME) && \ + tofu fmt && tofu init && tofu plan + +apply: + cd live/$(STACK_NAME) && \ + tofu apply --auto-approve + +quick: + @make plan + @make apply + +gke: export STACK_NAME=$(PREFIX)-gke +gke: + @make quick + +aks: export STACK_NAME=$(PREFIX)-aks +aks: + @make quick + +kind: export STACK_NAME=$(PREFIX)-kind +kind: + @make quick + +destroy: + cd live/$(STACK_NAME) && \ + tofu destroy --auto-approve + +clean: destroy + @cd live/$(STACK_NAME) && \ + rm -rf .terraform && rm terraform.tfstate && rm terraform.tfstate.backup + +kind-kubeconfig: + @kubectl config set-context live/$(PREFIX)-kind/mc-kind-config + +test: + @cd test && go test -v -count=1 -timeout 30m ./... diff --git a/test/multicloud/README.md b/test/multicloud/README.md new file mode 100644 index 0000000000..f82939a532 --- /dev/null +++ b/test/multicloud/README.md @@ -0,0 +1,98 @@ +# Multi Cloud Retina + +This project leverages [OpenTofu](https://opentofu.org/docs/intro/) Infrastructure as Code (IaC) to create Kubernetes infrastructure on multi-cloud and deploy [microsoft/retina](https://github.com/microsoft/retina) via Helm provider. + +![Architecture Diagram](./diagrams/diagram.svg) + +## Modules available + +* [aks](./modules/aks/) +* [gke](./modules/gke/) +* [kind](./modules/kind/) +* [retina](./modules/retina/) + +## Prerequisites + +* [OpenTofu installation guide](https://opentofu.org/docs/intro/install/) + +* AKS: + + 1. create an Azure account + 2. [Install az](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) + + To deploy an AKS cluster and install retina, create file `live/retina-aks/terraform.tfvars` with the Azure TenantID and SubscriptionID + + ```sh + # example values + subscription_id = "d6050d84-e4dd-463d-afc7-a6ab3dc33ab7" + tenant_id = "ac8a4ccd-35f1-4f95-a688-f68e3d89adfc" + ``` + +* GKE: + + 1. create a gcloud account, project and enable billing + 2. create a service account and service account key + 3. [Enable Kubernetes Engine API](https://console.developers.google.com/apis/api/container.googleapis.com/overview?project=mc-retina) + 4. [Install gcloud](https://cloud.google.com/sdk/docs/install) + + To deploy a GKE cluster export `GOOGLE_APPLICATION_CREDENTIALS` env variable to point to the path where your [service account key](https://cloud.google.com/iam/docs/keys-create-delete) is located. + + ```sh + # example + export GOOGLE_APPLICATION_CREDENTIALS=/Users/srodi/src/retina/test/multicloud/live/retina-gke/service-key.json + ``` + +* Kind: + + 1. Docker installed on the host machine + +## Quickstart + +The following Make targets can be used to manage each stack lifecycle. + +### Create + +Format code, initialize OpenTofu, plan and apply the stack to create infra and deploy retina + +* AKS: + + ```sh + make aks + ``` + +* GKE: + + ```sh + make gke + ``` + +* Kind: + + ```sh + make kind + ``` + +### Clean up + +To destroy the cluster specify the `STACK_NAME` and run `make clean`. + +```sh +# destroy AKS and cleanup local state files +# set a different stack as needed (i.e. retina-gke, retina-kind) +export STACK_NAME=retina-aks +make clean +``` + +### Test + +The test framework is levergaing Go and [Terratest](https://terratest.gruntwork.io/docs/). To run tests: + +```sh +make test +``` + +## Providers references + +* [GKE resource documentation](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/container_cluster) +* [AKS resource documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_cluster) +* [Kind resource documentation](https://registry.terraform.io/providers/tehcyx/kind/latest/docs/resources/cluster) diff --git a/test/multicloud/diagrams/diagram.excalidraw b/test/multicloud/diagrams/diagram.excalidraw new file mode 100644 index 0000000000..8049513551 --- /dev/null +++ b/test/multicloud/diagrams/diagram.excalidraw @@ -0,0 +1,3366 @@ +{ + "type": "excalidraw", + "version": 2, + "source": "https://excalidraw.com", + "elements": [ + { + "id": "zghIcLCzAMCMHoPa6KCP5", + "type": "rectangle", + "x": 919, + "y": 483, + "width": 286, + "height": 426, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "Zw", + "roundness": { + "type": 3 + }, + "seed": 618936138, + "version": 144, + "versionNonce": 1644653718, + "isDeleted": false, + "boundElements": [ + { + "id": "o_HSEmb0pecqRgBJDEBRp", + "type": "arrow" + }, + { + "id": "RBNxQ4pEgxmBXnHdIaBf9", + "type": "arrow" + }, + { + "id": "xhoCMjoiXLgPLJUmc7WuE", + "type": "arrow" + } + ], + "updated": 1737971092328, + "link": null, + "locked": false + }, + { + "id": "0S628Xmv8YIAFSDx8-05e", + "type": "rectangle", + "x": 1343, + "y": 443, + "width": 311, + "height": 503, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "Zx", + "roundness": { + "type": 3 + }, + "seed": 1054405910, + "version": 48, + "versionNonce": 564948438, + "isDeleted": false, + "boundElements": [ + { + "id": "HYF4G_hkcZFNdgAl0YQNb", + "type": "arrow" + }, + { + "id": "-4dHrHQZE2TDSvs-vgcAo", + "type": "arrow" + }, + { + "id": "o_HSEmb0pecqRgBJDEBRp", + "type": "arrow" + } + ], + "updated": 1737971037967, + "link": null, + "locked": false + }, + { + "id": "uLVKBxcndIG-qzR2NQnMF", + "type": "rectangle", + "x": 1854.5, + "y": 915.5, + "width": 311, + "height": 365.00000000000006, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "Zy", + "roundness": { + "type": 3 + }, + "seed": 1560720842, + "version": 336, + "versionNonce": 747983318, + "isDeleted": false, + "boundElements": [ + { + "id": "-4dHrHQZE2TDSvs-vgcAo", + "type": "arrow" + }, + { + "id": "RBNxQ4pEgxmBXnHdIaBf9", + "type": "arrow" + } + ], + "updated": 1737971057148, + "link": null, + "locked": false + }, + { + "id": "R4AeEioM2INhMP9rnYnHe", + "type": "rectangle", + "x": 1856.5, + "y": 347.5, + "width": 311, + "height": 503, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffc9c9", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "Zz", + "roundness": { + "type": 3 + }, + "seed": 719699734, + "version": 234, + "versionNonce": 37331222, + "isDeleted": false, + "boundElements": [ + { + "id": "r_IiMCnJET5n-m5aE4N6J", + "type": "arrow" + }, + { + "id": "HYF4G_hkcZFNdgAl0YQNb", + "type": "arrow" + }, + { + "id": "xhoCMjoiXLgPLJUmc7WuE", + "type": "arrow" + }, + { + "id": "1G4RvWl5j3Eq0orLwRNb1", + "type": "arrow" + }, + { + "id": "JenUnqPQU9n29FUsRjstV", + "type": "arrow" + } + ], + "updated": 1737971550725, + "link": null, + "locked": false + }, + { + "id": "zXqDMrjv50TU6s8f0xi2s", + "type": "rectangle", + "x": 1847.078125, + "y": -36, + "width": 231.859375, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0y", + "roundness": null, + "seed": 886375254, + "version": 125, + "versionNonce": 425608714, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "Eh9WaurLCaoIoY157lFTc" + }, + { + "id": "sSBpGKS5X6pi-Hat4HUBJ", + "type": "arrow" + }, + { + "id": "WlzkJ1a1P1Er7kfA1RP4T", + "type": "arrow" + } + ], + "updated": 1737971176481, + "link": null, + "locked": false + }, + { + "id": "O4E1OnJgXZMVXYZqcHbbf", + "type": "rectangle", + "x": 1881.3203125, + "y": 58, + "width": 163.375, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0z", + "roundness": null, + "seed": 558246038, + "version": 234, + "versionNonce": 1718596042, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "iafWgom0hD1fD-mok9szu" + }, + { + "id": "sSBpGKS5X6pi-Hat4HUBJ", + "type": "arrow" + }, + { + "id": "TxfM-J3QLXhdIlqgtcSp3", + "type": "arrow" + }, + { + "id": "r_IiMCnJET5n-m5aE4N6J", + "type": "arrow" + }, + { + "id": "J_prQC5yc7ywuZigF71Wh", + "type": "arrow" + } + ], + "updated": 1737971184547, + "link": null, + "locked": false + }, + { + "id": "ysLRakRFsF7DlEwBVIfpv", + "type": "rectangle", + "x": 2444.4140625, + "y": 74, + "width": 225.65625, + "height": 60, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b12", + "roundness": null, + "seed": 1464182870, + "version": 847, + "versionNonce": 1974440970, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "UoF1VeVtOBF-B_pHGbkiD" + }, + { + "id": "WlzkJ1a1P1Er7kfA1RP4T", + "type": "arrow" + }, + { + "id": "EL7fKQS2Z0a_heFdNlDpe", + "type": "arrow" + }, + { + "id": "-FO1qNsJmZSIC7MG10S17", + "type": "arrow" + } + ], + "updated": 1737971476328, + "link": null, + "locked": false + }, + { + "id": "9pGuk9pLc645Jva07NwPP", + "type": "rectangle", + "x": 1417.08984375, + "y": 503, + "width": 143.453125, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b13", + "roundness": null, + "seed": 1482304918, + "version": 54, + "versionNonce": 1221402454, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "n6fgzgLn1UV2wrjYVoVDr" + } + ], + "updated": 1737970947812, + "link": null, + "locked": false + }, + { + "id": "nlTAqIR7zMcS6PGUnUiPG", + "type": "rectangle", + "x": 1420.06640625, + "y": 704, + "width": 154.921875, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b14", + "roundness": null, + "seed": 1730939606, + "version": 93, + "versionNonce": 1874844694, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "RK06UCyMyn_5XDjMl8d_D" + } + ], + "updated": 1737970950262, + "link": null, + "locked": false + }, + { + "id": "fz7IX_5gQKgv9w7KWCF9F", + "type": "rectangle", + "x": 1415.05078125, + "y": 796, + "width": 173.296875, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b15", + "roundness": null, + "seed": 307249174, + "version": 137, + "versionNonce": 234210442, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "kgSbIGb4Oi7kNTwp2QkrU" + } + ], + "updated": 1737970951221, + "link": null, + "locked": false + }, + { + "id": "oKOWo7KV9Y8J3AQR1lX-P", + "type": "rectangle", + "x": 989.09765625, + "y": 805, + "width": 153.20312500000003, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1C", + "roundness": null, + "seed": 2062767318, + "version": 226, + "versionNonce": 700710410, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "YBOf_ZI3--rqMICNXDl5o" + } + ], + "updated": 1737970946099, + "link": null, + "locked": false + }, + { + "id": "xPpUhfUnNbsMPlojZlr0W", + "type": "rectangle", + "x": 980.1328125, + "y": 543, + "width": 162.078125, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [ + "klCQzqbRxuqhJ44QC9Oku" + ], + "frameId": null, + "index": "b1E", + "roundness": null, + "seed": 1538824022, + "version": 267, + "versionNonce": 763874250, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "03ZfRAoP-dkIsVdwuMcGm" + } + ], + "updated": 1737970941082, + "link": null, + "locked": false + }, + { + "id": "sSBpGKS5X6pi-Hat4HUBJ", + "type": "arrow", + "x": 1963.00803125, + "y": 8.5, + "width": 0, + "height": 43.699999999999996, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1F", + "roundness": { + "type": 2 + }, + "seed": 1318534294, + "version": 467, + "versionNonce": 2147339786, + "isDeleted": false, + "boundElements": [], + "updated": 1737971184547, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 43.699999999999996 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "zXqDMrjv50TU6s8f0xi2s", + "focus": -0.000001886919603150646, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "O4E1OnJgXZMVXYZqcHbbf", + "focus": 0.0000026778882929564303, + "gap": 5.799999999999997, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "Eh9WaurLCaoIoY157lFTc", + "type": "text", + "x": 1869.5478744506836, + "y": -26.5, + "width": 186.9198760986328, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1Z", + "roundness": null, + "seed": 570447254, + "version": 124, + "versionNonce": 1946965270, + "isDeleted": false, + "boundElements": [], + "updated": 1737970467013, + "link": null, + "locked": false, + "text": "Multi-Cloud Project", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "zXqDMrjv50TU6s8f0xi2s", + "originalText": "Multi-Cloud Project", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "iafWgom0hD1fD-mok9szu", + "type": "text", + "x": 1893.917854309082, + "y": 67.5, + "width": 138.17991638183594, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1a", + "roundness": null, + "seed": 1775055574, + "version": 225, + "versionNonce": 1441458314, + "isDeleted": false, + "boundElements": [], + "updated": 1737971184547, + "link": null, + "locked": false, + "text": "OpenTofu IaC", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "O4E1OnJgXZMVXYZqcHbbf", + "originalText": "OpenTofu IaC", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "UoF1VeVtOBF-B_pHGbkiD", + "type": "text", + "x": 2499.9722213745117, + "y": 79, + "width": 114.53993225097656, + "height": 50, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1d", + "roundness": null, + "seed": 404085398, + "version": 838, + "versionNonce": 911934358, + "isDeleted": false, + "boundElements": [], + "updated": 1737971223954, + "link": null, + "locked": false, + "text": "GO Testing\nFramework", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "ysLRakRFsF7DlEwBVIfpv", + "originalText": "GO Testing Framework", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "n6fgzgLn1UV2wrjYVoVDr", + "type": "text", + "x": 1465.7064208984375, + "y": 512.5, + "width": 46.219970703125, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1e", + "roundness": null, + "seed": 1827280854, + "version": 48, + "versionNonce": 2005438678, + "isDeleted": false, + "boundElements": [], + "updated": 1737970219802, + "link": null, + "locked": false, + "text": "AKS ", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "9pGuk9pLc645Jva07NwPP", + "originalText": "AKS ", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "RK06UCyMyn_5XDjMl8d_D", + "type": "text", + "x": 1471.6273498535156, + "y": 713.5, + "width": 51.79998779296875, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1f", + "roundness": null, + "seed": 784641302, + "version": 94, + "versionNonce": 1999275926, + "isDeleted": false, + "boundElements": [], + "updated": 1737970228691, + "link": null, + "locked": false, + "text": "KIND", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "nlTAqIR7zMcS6PGUnUiPG", + "originalText": "KIND", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "kgSbIGb4Oi7kNTwp2QkrU", + "type": "text", + "x": 1469.239242553711, + "y": 805.5, + "width": 64.91995239257812, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1g", + "roundness": null, + "seed": 454728278, + "version": 136, + "versionNonce": 1384911050, + "isDeleted": false, + "boundElements": [], + "updated": 1737970238236, + "link": null, + "locked": false, + "text": "Retina", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "fz7IX_5gQKgv9w7KWCF9F", + "originalText": "Retina", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "YBOf_ZI3--rqMICNXDl5o", + "type": "text", + "x": 1041.7192306518555, + "y": 814.5, + "width": 47.95997619628906, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1n", + "roundness": null, + "seed": 1108719382, + "version": 222, + "versionNonce": 1030092746, + "isDeleted": false, + "boundElements": [], + "updated": 1737970255474, + "link": null, + "locked": false, + "text": "Helm ", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "oKOWo7KV9Y8J3AQR1lX-P", + "originalText": "Helm ", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "03ZfRAoP-dkIsVdwuMcGm", + "type": "text", + "x": 1033.291893005371, + "y": 552.5, + "width": 55.75996398925781, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [ + "klCQzqbRxuqhJ44QC9Oku" + ], + "frameId": null, + "index": "b1p", + "roundness": null, + "seed": 2128046486, + "version": 267, + "versionNonce": 1559104842, + "isDeleted": false, + "boundElements": [], + "updated": 1737970255474, + "link": null, + "locked": false, + "text": "Azure", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "xPpUhfUnNbsMPlojZlr0W", + "originalText": "Azure", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "U6X68vlOQPsistV7KGQj7", + "type": "rectangle", + "x": 982.9609375, + "y": 716, + "width": 162.078125, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [ + "8IJVdH1tDYshWtx-RzqUy" + ], + "frameId": null, + "index": "b1u", + "roundness": null, + "seed": 1066099146, + "version": 321, + "versionNonce": 1510947478, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "n5AzOpyhjDk4cJALwlppo" + } + ], + "updated": 1737970944829, + "link": null, + "locked": false + }, + { + "id": "n5AzOpyhjDk4cJALwlppo", + "type": "text", + "x": 1038.1000061035156, + "y": 725.5, + "width": 51.79998779296875, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [ + "8IJVdH1tDYshWtx-RzqUy" + ], + "frameId": null, + "index": "b1v", + "roundness": null, + "seed": 1880135818, + "version": 337, + "versionNonce": 110019274, + "isDeleted": false, + "boundElements": [], + "updated": 1737970255474, + "link": null, + "locked": false, + "text": "KIND", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "U6X68vlOQPsistV7KGQj7", + "originalText": "KIND", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "6vHcegO-bhhAWthKg5DLF", + "type": "rectangle", + "x": 982.9609375, + "y": 632, + "width": 162.078125, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [ + "dBEY2fEZd5U8JDWibmeLQ" + ], + "frameId": null, + "index": "b1w", + "roundness": null, + "seed": 2042518742, + "version": 322, + "versionNonce": 2099680970, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "7FCUVEMtLqp4KBg0vB5g0" + } + ], + "updated": 1737970943673, + "link": null, + "locked": false + }, + { + "id": "7FCUVEMtLqp4KBg0vB5g0", + "type": "text", + "x": 1000.5100250244141, + "y": 641.5, + "width": 126.97994995117188, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [ + "dBEY2fEZd5U8JDWibmeLQ" + ], + "frameId": null, + "index": "b1x", + "roundness": null, + "seed": 46682646, + "version": 338, + "versionNonce": 1151342666, + "isDeleted": false, + "boundElements": [], + "updated": 1737970255474, + "link": null, + "locked": false, + "text": "Google Cloud", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "6vHcegO-bhhAWthKg5DLF", + "originalText": "Google Cloud", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "cvMVx90aAz8Snv2pIMyEP", + "type": "rectangle", + "x": 1422.2734375, + "y": 610, + "width": 143.453125, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1y", + "roundness": null, + "seed": 504440010, + "version": 148, + "versionNonce": 1612320074, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "7x5KHRGKh6towsi_8LYpB" + } + ], + "updated": 1737970949157, + "link": null, + "locked": false + }, + { + "id": "7x5KHRGKh6towsi_8LYpB", + "type": "text", + "x": 1472.5700073242188, + "y": 619.5, + "width": 42.8599853515625, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1z", + "roundness": null, + "seed": 518388618, + "version": 144, + "versionNonce": 1811483594, + "isDeleted": false, + "boundElements": [], + "updated": 1737970242587, + "link": null, + "locked": false, + "text": "GKE", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "cvMVx90aAz8Snv2pIMyEP", + "originalText": "GKE", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "w-30O_eesbT44MY2r9VIi", + "type": "text", + "x": 1544, + "y": 455, + "width": 76.61996459960938, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b21", + "roundness": null, + "seed": 274873098, + "version": 33, + "versionNonce": 344674902, + "isDeleted": false, + "boundElements": [ + { + "id": "TxfM-J3QLXhdIlqgtcSp3", + "type": "arrow" + } + ], + "updated": 1737970326763, + "link": null, + "locked": false, + "text": "Modules", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Modules", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "A19y-iFjO8jPxtueSWwhh", + "type": "text", + "x": 1090, + "y": 497, + "width": 92.65994262695312, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b23", + "roundness": null, + "seed": 1289638218, + "version": 41, + "versionNonce": 1506505930, + "isDeleted": false, + "boundElements": null, + "updated": 1737970297494, + "link": null, + "locked": false, + "text": "Providers", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Providers", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "TxfM-J3QLXhdIlqgtcSp3", + "type": "arrow", + "x": 1971.3696285377284, + "y": 103, + "width": 395.36962853772843, + "height": 341, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b28", + "roundness": { + "type": 2 + }, + "seed": 1369408406, + "version": 163, + "versionNonce": 1645571990, + "isDeleted": false, + "boundElements": null, + "updated": 1737971184547, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -395.36962853772843, + 341 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "O4E1OnJgXZMVXYZqcHbbf", + "focus": -0.32677741038380365, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "w-30O_eesbT44MY2r9VIi", + "focus": -0.8955844703788051, + "gap": 11, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "8AUKqnBI6Ff1R4wt0slqa", + "type": "rectangle", + "x": 1930.58984375, + "y": 407.5, + "width": 143.453125, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b29", + "roundness": null, + "seed": 1981592854, + "version": 231, + "versionNonce": 1503908374, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "eoIm4zi0FVKJOECWWL7TP" + } + ], + "updated": 1737970947812, + "link": null, + "locked": false + }, + { + "id": "Rg3n2f_ms7-kJ94iZVPrE", + "type": "rectangle", + "x": 1933.56640625, + "y": 608.5, + "width": 154.921875, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2A", + "roundness": null, + "seed": 1244766806, + "version": 270, + "versionNonce": 1096754902, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "k5JMWXVEMnO8AA6zcZaht" + } + ], + "updated": 1737970950262, + "link": null, + "locked": false + }, + { + "id": "cK83p_ezogmd5Hf_eZwz2", + "type": "rectangle", + "x": 1928.55078125, + "y": 700.5, + "width": 173.296875, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2B", + "roundness": null, + "seed": 1068951446, + "version": 314, + "versionNonce": 497421770, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "7ok5BbnOLbhPq6AgN4GYB" + } + ], + "updated": 1737970951221, + "link": null, + "locked": false + }, + { + "id": "eoIm4zi0FVKJOECWWL7TP", + "type": "text", + "x": 1979.2064208984375, + "y": 417, + "width": 46.219970703125, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2C", + "roundness": null, + "seed": 1994491094, + "version": 226, + "versionNonce": 1844995478, + "isDeleted": false, + "boundElements": [], + "updated": 1737970406988, + "link": null, + "locked": false, + "text": "AKS ", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "8AUKqnBI6Ff1R4wt0slqa", + "originalText": "AKS ", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "k5JMWXVEMnO8AA6zcZaht", + "type": "text", + "x": 1985.1273498535156, + "y": 618, + "width": 51.79998779296875, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2D", + "roundness": null, + "seed": 1095137814, + "version": 272, + "versionNonce": 543491414, + "isDeleted": false, + "boundElements": [], + "updated": 1737970406988, + "link": null, + "locked": false, + "text": "KIND", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "Rg3n2f_ms7-kJ94iZVPrE", + "originalText": "KIND", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "7ok5BbnOLbhPq6AgN4GYB", + "type": "text", + "x": 1982.739242553711, + "y": 710, + "width": 64.91995239257812, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2E", + "roundness": null, + "seed": 1977272150, + "version": 314, + "versionNonce": 1165016342, + "isDeleted": false, + "boundElements": [], + "updated": 1737970406988, + "link": null, + "locked": false, + "text": "Retina", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "cK83p_ezogmd5Hf_eZwz2", + "originalText": "Retina", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "BFUrWgvUgo1Tm7uLzxqJb", + "type": "rectangle", + "x": 1935.7734375, + "y": 514.5, + "width": 143.453125, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2F", + "roundness": null, + "seed": 1156803734, + "version": 325, + "versionNonce": 987000458, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "q3iv3crLU6YUmmSjnjJ7r" + } + ], + "updated": 1737970949157, + "link": null, + "locked": false + }, + { + "id": "q3iv3crLU6YUmmSjnjJ7r", + "type": "text", + "x": 1986.0700073242188, + "y": 524, + "width": 42.8599853515625, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2G", + "roundness": null, + "seed": 205875670, + "version": 322, + "versionNonce": 995265750, + "isDeleted": false, + "boundElements": [], + "updated": 1737970406989, + "link": null, + "locked": false, + "text": "GKE", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "BFUrWgvUgo1Tm7uLzxqJb", + "originalText": "GKE", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "0zdoqgDRvg-ebTICP9SFX", + "type": "text", + "x": 2057.5, + "y": 359.5, + "width": 87.31996154785156, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2I", + "roundness": null, + "seed": 1430875222, + "version": 219, + "versionNonce": 1470198934, + "isDeleted": false, + "boundElements": [], + "updated": 1737970406989, + "link": null, + "locked": false, + "text": "Examples", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Examples", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "2YGILj7S2n9PeADdx2TMY", + "type": "rectangle", + "x": 1928.58984375, + "y": 975.5, + "width": 143.453125, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2N", + "roundness": null, + "seed": 739942346, + "version": 263, + "versionNonce": 2047805078, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "A_JFPEAqBW9EPietZYM8a" + } + ], + "updated": 1737970455777, + "link": null, + "locked": false + }, + { + "id": "mIlz4x0AjaordLAqI-DWY", + "type": "rectangle", + "x": 1931.56640625, + "y": 1176.5, + "width": 154.921875, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2O", + "roundness": null, + "seed": 1141380746, + "version": 302, + "versionNonce": 761452822, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "uv0MN_ZBtwcWuq7WETscI" + } + ], + "updated": 1737970455778, + "link": null, + "locked": false + }, + { + "id": "A_JFPEAqBW9EPietZYM8a", + "type": "text", + "x": 1944.996452331543, + "y": 985, + "width": 110.63990783691406, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2Q", + "roundness": null, + "seed": 791116810, + "version": 269, + "versionNonce": 249414614, + "isDeleted": false, + "boundElements": [], + "updated": 1737970455778, + "link": null, + "locked": false, + "text": "Retina-AKS", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "2YGILj7S2n9PeADdx2TMY", + "originalText": "Retina-AKS", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "uv0MN_ZBtwcWuq7WETscI", + "type": "text", + "x": 1946.7973861694336, + "y": 1186, + "width": 124.45991516113281, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2R", + "roundness": null, + "seed": 1102015178, + "version": 318, + "versionNonce": 2098415190, + "isDeleted": false, + "boundElements": [], + "updated": 1737970455778, + "link": null, + "locked": false, + "text": "Retina-KIND", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "mIlz4x0AjaordLAqI-DWY", + "originalText": "Retina-KIND", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "y5OM8zL9aH4eV1vQRfRA8", + "type": "rectangle", + "x": 1933.7734375, + "y": 1082.5, + "width": 143.453125, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2T", + "roundness": null, + "seed": 1572257866, + "version": 357, + "versionNonce": 1858341782, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "cgV-AqaregAAVrxZQQPP7" + } + ], + "updated": 1737970455778, + "link": null, + "locked": false + }, + { + "id": "cgV-AqaregAAVrxZQQPP7", + "type": "text", + "x": 1948.2400436401367, + "y": 1092, + "width": 114.51991271972656, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2U", + "roundness": null, + "seed": 508307210, + "version": 365, + "versionNonce": 279587030, + "isDeleted": false, + "boundElements": [], + "updated": 1737970455778, + "link": null, + "locked": false, + "text": "Retina-GKE", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "y5OM8zL9aH4eV1vQRfRA8", + "originalText": "Retina-GKE", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "CDhoAiwZsuutyGpxSBtr1", + "type": "text", + "x": 2055.5, + "y": 927.5, + "width": 37.23997497558594, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2W", + "roundness": null, + "seed": 1795255434, + "version": 257, + "versionNonce": 80994134, + "isDeleted": false, + "boundElements": [ + { + "id": "J_prQC5yc7ywuZigF71Wh", + "type": "arrow" + } + ], + "updated": 1737970481192, + "link": null, + "locked": false, + "text": "Live", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Live", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "r_IiMCnJET5n-m5aE4N6J", + "type": "arrow", + "x": 1972, + "y": 107, + "width": 6.9854166666666515, + "height": 239.5, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2Y", + "roundness": { + "type": 2 + }, + "seed": 1848447382, + "version": 149, + "versionNonce": 132873418, + "isDeleted": false, + "boundElements": null, + "updated": 1737971184548, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 6.9854166666666515, + 239.5 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "O4E1OnJgXZMVXYZqcHbbf", + "focus": -0.09965711827521635, + "gap": 5, + "fixedPoint": null + }, + "endBinding": { + "elementId": "R4AeEioM2INhMP9rnYnHe", + "focus": -0.15752101431660293, + "gap": 1, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "J_prQC5yc7ywuZigF71Wh", + "type": "arrow", + "x": 1973, + "y": 106.99999999999989, + "width": 388, + "height": 812.0000000000001, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2Z", + "roundness": { + "type": 2 + }, + "seed": 26578774, + "version": 401, + "versionNonce": 876832714, + "isDeleted": false, + "boundElements": [], + "updated": 1737971284718, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 388, + 564.0000000000001 + ], + [ + 84, + 812.0000000000001 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "O4E1OnJgXZMVXYZqcHbbf", + "focus": 0.0886395475001259, + "gap": 5, + "fixedPoint": null + }, + "endBinding": { + "elementId": "CDhoAiwZsuutyGpxSBtr1", + "focus": -1.262777842966161, + "gap": 8.5, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "HYF4G_hkcZFNdgAl0YQNb", + "type": "arrow", + "x": 1858, + "y": 607, + "width": 207, + "height": 5, + "angle": 0, + "strokeColor": "#1971c2", + "backgroundColor": "#a5d8ff", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2a", + "roundness": { + "type": 2 + }, + "seed": 1979137814, + "version": 57, + "versionNonce": 1112572054, + "isDeleted": false, + "boundElements": null, + "updated": 1737971124821, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -207, + 5 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "R4AeEioM2INhMP9rnYnHe", + "focus": -0.01676823498239903, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "0S628Xmv8YIAFSDx8-05e", + "focus": -0.3087739884174268, + "gap": 1, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "nm5O_cFaqDOe1J9pTEhmu", + "type": "text", + "x": 1708, + "y": 574, + "width": 125.63990783691406, + "height": 25, + "angle": 0, + "strokeColor": "#1971c2", + "backgroundColor": "#a5d8ff", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2b", + "roundness": null, + "seed": 183796746, + "version": 85, + "versionNonce": 62722378, + "isDeleted": false, + "boundElements": null, + "updated": 1737971128309, + "link": null, + "locked": false, + "text": "Instantiates", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Instantiates", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "VBZOWyP-GhRCxXcLTHwB_", + "type": "text", + "x": 1657.180046081543, + "y": 1047.5, + "width": 125.63990783691406, + "height": 25, + "angle": 0, + "strokeColor": "#1971c2", + "backgroundColor": "#a5d8ff", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2c", + "roundness": null, + "seed": 739676554, + "version": 124, + "versionNonce": 2038259082, + "isDeleted": false, + "boundElements": [], + "updated": 1737971132189, + "link": null, + "locked": false, + "text": "Instantiates", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Instantiates", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "-4dHrHQZE2TDSvs-vgcAo", + "type": "arrow", + "x": 1853, + "y": 1104, + "width": 200, + "height": 187, + "angle": 0, + "strokeColor": "#1971c2", + "backgroundColor": "#a5d8ff", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2d", + "roundness": { + "type": 2 + }, + "seed": 471021322, + "version": 35, + "versionNonce": 2134311690, + "isDeleted": false, + "boundElements": null, + "updated": 1737971136385, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -200, + -187 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "uLVKBxcndIG-qzR2NQnMF", + "focus": -0.4659911403889994, + "gap": 1.5, + "fixedPoint": null + }, + "endBinding": { + "elementId": "0S628Xmv8YIAFSDx8-05e", + "focus": 0.19663384921609758, + "gap": 1, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "o_HSEmb0pecqRgBJDEBRp", + "type": "arrow", + "x": 1343, + "y": 673, + "width": 136, + "height": 4, + "angle": 0, + "strokeColor": "#f08c00", + "backgroundColor": "#a5d8ff", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2e", + "roundness": { + "type": 2 + }, + "seed": 144078154, + "version": 29, + "versionNonce": 1175139926, + "isDeleted": false, + "boundElements": null, + "updated": 1737971114288, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -136, + 4 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "0S628Xmv8YIAFSDx8-05e", + "focus": 0.10182047895250676, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "zghIcLCzAMCMHoPa6KCP5", + "focus": -0.06784021665538253, + "gap": 2, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "13azSEVgK_dcdndesOJU4", + "type": "text", + "x": 1271, + "y": 644, + "width": 47.19996643066406, + "height": 25, + "angle": 0, + "strokeColor": "#f08c00", + "backgroundColor": "#a5d8ff", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2f", + "roundness": null, + "seed": 1546120586, + "version": 7, + "versionNonce": 591726474, + "isDeleted": false, + "boundElements": null, + "updated": 1737971117472, + "link": null, + "locked": false, + "text": "Uses", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Uses", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "JMh5UJvRSjgcfPdc_YCR7", + "type": "text", + "x": 1597.400016784668, + "y": 1134.5, + "width": 47.19996643066406, + "height": 25, + "angle": 0, + "strokeColor": "#f08c00", + "backgroundColor": "#a5d8ff", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2g", + "roundness": null, + "seed": 1271206422, + "version": 3, + "versionNonce": 1160150, + "isDeleted": false, + "boundElements": null, + "updated": 1737971110710, + "link": null, + "locked": false, + "text": "Uses", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Uses", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "RBNxQ4pEgxmBXnHdIaBf9", + "type": "arrow", + "x": 1854, + "y": 1110, + "width": 758, + "height": 242, + "angle": 0, + "strokeColor": "#f08c00", + "backgroundColor": "#a5d8ff", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2h", + "roundness": { + "type": 2 + }, + "seed": 2027055370, + "version": 185, + "versionNonce": 450718806, + "isDeleted": false, + "boundElements": null, + "updated": 1737971102355, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -326, + 51 + ], + [ + -758, + -191 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "uLVKBxcndIG-qzR2NQnMF", + "focus": 0.05997730828840719, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "zghIcLCzAMCMHoPa6KCP5", + "focus": 0.6958348470250035, + "gap": 10, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "k-K-sqJPwGdOAbF7FgGcz", + "type": "text", + "x": 1512.400016784668, + "y": 262.5, + "width": 47.19996643066406, + "height": 25, + "angle": 0, + "strokeColor": "#f08c00", + "backgroundColor": "#a5d8ff", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2i", + "roundness": null, + "seed": 1588338186, + "version": 3, + "versionNonce": 1246659606, + "isDeleted": false, + "boundElements": null, + "updated": 1737971106415, + "link": null, + "locked": false, + "text": "Uses", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Uses", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "xhoCMjoiXLgPLJUmc7WuE", + "type": "arrow", + "x": 1858, + "y": 605, + "width": 795, + "height": 311, + "angle": 0, + "strokeColor": "#f08c00", + "backgroundColor": "#a5d8ff", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2j", + "roundness": { + "type": 2 + }, + "seed": 1794620630, + "version": 236, + "versionNonce": 489375370, + "isDeleted": false, + "boundElements": null, + "updated": 1737971095964, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -277, + -311 + ], + [ + -795, + -122 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "R4AeEioM2INhMP9rnYnHe", + "focus": -0.4198735871757071, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "zghIcLCzAMCMHoPa6KCP5", + "focus": -0.8018651582326861, + "gap": 1, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "WlzkJ1a1P1Er7kfA1RP4T", + "type": "arrow", + "x": 1964, + "y": 9, + "width": 474, + "height": 84.63600506869611, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2k", + "roundness": { + "type": 2 + }, + "seed": 217245642, + "version": 192, + "versionNonce": 227064650, + "isDeleted": false, + "boundElements": null, + "updated": 1737971481423, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 249, + 24 + ], + [ + 474, + 84.63600506869611 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "zXqDMrjv50TU6s8f0xi2s", + "focus": 0.6904324140279195, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "ysLRakRFsF7DlEwBVIfpv", + "focus": -0.3604083592296213, + "gap": 6.4140625, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "0jJYOpQUuReGklXS3eCHd", + "type": "rectangle", + "x": 2433.5, + "y": 357.5, + "width": 311, + "height": 503, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2p", + "roundness": { + "type": 3 + }, + "seed": 507557578, + "version": 387, + "versionNonce": 1340323542, + "isDeleted": false, + "boundElements": [ + { + "id": "EL7fKQS2Z0a_heFdNlDpe", + "type": "arrow" + }, + { + "id": "1G4RvWl5j3Eq0orLwRNb1", + "type": "arrow" + } + ], + "updated": 1737971510934, + "link": null, + "locked": false + }, + { + "id": "yXs1C5HAV_quiAwVGmj9-", + "type": "rectangle", + "x": 2507.58984375, + "y": 417.5, + "width": 143.453125, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2q", + "roundness": null, + "seed": 1465077130, + "version": 383, + "versionNonce": 1531846538, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "c-HWcR62JO098FZH-Exyy" + } + ], + "updated": 1737971303713, + "link": null, + "locked": false + }, + { + "id": "XKA3gCRYDhwXJMOPsnTYe", + "type": "rectangle", + "x": 2510.56640625, + "y": 618.5, + "width": 154.921875, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2r", + "roundness": null, + "seed": 1734675530, + "version": 422, + "versionNonce": 289359114, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "UPzd8AvyIY1ANthQMQL-2" + } + ], + "updated": 1737971303713, + "link": null, + "locked": false + }, + { + "id": "sVoinvy16hzPyLe8OLqLD", + "type": "rectangle", + "x": 2505.55078125, + "y": 710.5, + "width": 173.296875, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2s", + "roundness": null, + "seed": 1951462154, + "version": 466, + "versionNonce": 1984236170, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "r_UUPiappL6TFrgWoMu3T" + } + ], + "updated": 1737971303713, + "link": null, + "locked": false + }, + { + "id": "c-HWcR62JO098FZH-Exyy", + "type": "text", + "x": 2556.2064208984375, + "y": 427, + "width": 46.219970703125, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2t", + "roundness": null, + "seed": 814875082, + "version": 378, + "versionNonce": 137731658, + "isDeleted": false, + "boundElements": [], + "updated": 1737971303713, + "link": null, + "locked": false, + "text": "AKS ", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "yXs1C5HAV_quiAwVGmj9-", + "originalText": "AKS ", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "UPzd8AvyIY1ANthQMQL-2", + "type": "text", + "x": 2562.1273498535156, + "y": 628, + "width": 51.79998779296875, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2u", + "roundness": null, + "seed": 1195587722, + "version": 424, + "versionNonce": 2145784778, + "isDeleted": false, + "boundElements": [], + "updated": 1737971303713, + "link": null, + "locked": false, + "text": "KIND", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "XKA3gCRYDhwXJMOPsnTYe", + "originalText": "KIND", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "r_UUPiappL6TFrgWoMu3T", + "type": "text", + "x": 2559.739242553711, + "y": 720, + "width": 64.91995239257812, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2v", + "roundness": null, + "seed": 1210029898, + "version": 466, + "versionNonce": 454502730, + "isDeleted": false, + "boundElements": [], + "updated": 1737971303713, + "link": null, + "locked": false, + "text": "Retina", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "sVoinvy16hzPyLe8OLqLD", + "originalText": "Retina", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "DTsWo6ztMP02RFmBj6e-D", + "type": "rectangle", + "x": 2512.7734375, + "y": 524.5, + "width": 143.453125, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2w", + "roundness": null, + "seed": 327294474, + "version": 477, + "versionNonce": 95907850, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "pRnKaRijr0r7prQVxvfOw" + } + ], + "updated": 1737971303713, + "link": null, + "locked": false + }, + { + "id": "pRnKaRijr0r7prQVxvfOw", + "type": "text", + "x": 2563.0700073242188, + "y": 534, + "width": 42.8599853515625, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2x", + "roundness": null, + "seed": 1181076682, + "version": 474, + "versionNonce": 706797258, + "isDeleted": false, + "boundElements": [], + "updated": 1737971303713, + "link": null, + "locked": false, + "text": "GKE", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "DTsWo6ztMP02RFmBj6e-D", + "originalText": "GKE", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "K11qeT79l6Z6nKat1Vns3", + "type": "text", + "x": 2663.5, + "y": 371.5, + "width": 41.059967041015625, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2y", + "roundness": null, + "seed": 644195210, + "version": 430, + "versionNonce": 347405066, + "isDeleted": false, + "boundElements": [], + "updated": 1737971373887, + "link": null, + "locked": false, + "text": "Unit", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Unit", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "GdXv0Fvpyz0tdxI9bskx0", + "type": "rectangle", + "x": 2830.5, + "y": 429.5, + "width": 311, + "height": 350, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2z", + "roundness": { + "type": 3 + }, + "seed": 1407292694, + "version": 536, + "versionNonce": 1282920086, + "isDeleted": false, + "boundElements": [ + { + "id": "JenUnqPQU9n29FUsRjstV", + "type": "arrow" + } + ], + "updated": 1737971550724, + "link": null, + "locked": false + }, + { + "id": "45JovtXM2WCeBgd46-RNa", + "type": "rectangle", + "x": 2904.58984375, + "y": 489.5, + "width": 143.453125, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b30", + "roundness": null, + "seed": 1549435478, + "version": 516, + "versionNonce": 1433501270, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "KK9wBCN7chtrFnhnHDCnN" + } + ], + "updated": 1737971415407, + "link": null, + "locked": false + }, + { + "id": "1UpFRPtuqe5oDMaRyOIOy", + "type": "rectangle", + "x": 2907.56640625, + "y": 690.5, + "width": 154.921875, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b31", + "roundness": null, + "seed": 1506002838, + "version": 555, + "versionNonce": 551182550, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "EebjZsSTiA0RgmiXs7pw-" + } + ], + "updated": 1737971415407, + "link": null, + "locked": false + }, + { + "id": "KK9wBCN7chtrFnhnHDCnN", + "type": "text", + "x": 2917.7764587402344, + "y": 499, + "width": 117.07989501953125, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b33", + "roundness": null, + "seed": 630938134, + "version": 548, + "versionNonce": 245056406, + "isDeleted": false, + "boundElements": [], + "updated": 1737971415407, + "link": null, + "locked": false, + "text": "Retina-AKS ", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "45JovtXM2WCeBgd46-RNa", + "originalText": "Retina-AKS ", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "EebjZsSTiA0RgmiXs7pw-", + "type": "text", + "x": 2922.7973861694336, + "y": 700, + "width": 124.45991516113281, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b34", + "roundness": null, + "seed": 1016309590, + "version": 594, + "versionNonce": 1875105302, + "isDeleted": false, + "boundElements": [], + "updated": 1737971415407, + "link": null, + "locked": false, + "text": "Retina-KIND", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "1UpFRPtuqe5oDMaRyOIOy", + "originalText": "Retina-KIND", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "fnS2X4EuJY-tTrtQBIe8A", + "type": "rectangle", + "x": 2909.7734375, + "y": 596.5, + "width": 143.453125, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b36", + "roundness": null, + "seed": 1648773590, + "version": 610, + "versionNonce": 609002326, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "82dXVu6Pnfd0kT49q4C9w" + } + ], + "updated": 1737971415407, + "link": null, + "locked": false + }, + { + "id": "82dXVu6Pnfd0kT49q4C9w", + "type": "text", + "x": 2924.2400436401367, + "y": 606, + "width": 114.51991271972656, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b37", + "roundness": null, + "seed": 1305124630, + "version": 644, + "versionNonce": 13224086, + "isDeleted": false, + "boundElements": [], + "updated": 1737971415407, + "link": null, + "locked": false, + "text": "Retina-GKE", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "fnS2X4EuJY-tTrtQBIe8A", + "originalText": "Retina-GKE", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "0xZrHBzEv0Ezz_B9ggGOG", + "type": "text", + "x": 3006.5, + "y": 443.5, + "width": 111.73991394042969, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b38", + "roundness": null, + "seed": 143805526, + "version": 578, + "versionNonce": 674077066, + "isDeleted": false, + "boundElements": [ + { + "id": "-FO1qNsJmZSIC7MG10S17", + "type": "arrow" + } + ], + "updated": 1737971476328, + "link": null, + "locked": false, + "text": "Integration", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Integration", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "EL7fKQS2Z0a_heFdNlDpe", + "type": "arrow", + "x": 2560, + "y": 138, + "width": 0, + "height": 217, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b39", + "roundness": { + "type": 2 + }, + "seed": 328428886, + "version": 28, + "versionNonce": 1900773450, + "isDeleted": false, + "boundElements": null, + "updated": 1737971470062, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 217 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "ysLRakRFsF7DlEwBVIfpv", + "focus": -0.024442597978119374, + "gap": 4, + "fixedPoint": null + }, + "endBinding": { + "elementId": "0jJYOpQUuReGklXS3eCHd", + "focus": -0.1864951768488746, + "gap": 2.5, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "-FO1qNsJmZSIC7MG10S17", + "type": "arrow", + "x": 2562, + "y": 135, + "width": 443, + "height": 297, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b3A", + "roundness": { + "type": 2 + }, + "seed": 634268810, + "version": 62, + "versionNonce": 1354947210, + "isDeleted": false, + "boundElements": null, + "updated": 1737971477960, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 318, + 94 + ], + [ + 443, + 297 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "ysLRakRFsF7DlEwBVIfpv", + "focus": 0.46713186808073004, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "0xZrHBzEv0Ezz_B9ggGOG", + "focus": -0.6700273879929672, + "gap": 11.5, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "1G4RvWl5j3Eq0orLwRNb1", + "type": "arrow", + "x": 2429, + "y": 587, + "width": 262, + "height": 17, + "angle": 0, + "strokeColor": "#e03131", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b3B", + "roundness": { + "type": 2 + }, + "seed": 383119562, + "version": 49, + "versionNonce": 607055690, + "isDeleted": false, + "boundElements": null, + "updated": 1737971531455, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -262, + 17 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "0jJYOpQUuReGklXS3eCHd", + "focus": 0.12378805454028145, + "gap": 4.5, + "fixedPoint": null + }, + "endBinding": { + "elementId": "R4AeEioM2INhMP9rnYnHe", + "focus": 0.0575605699153006, + "gap": 1, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "ia3p_InHfk6eqkomGTQVy", + "type": "text", + "x": 2352, + "y": 558, + "width": 47.19996643066406, + "height": 25, + "angle": 0, + "strokeColor": "#e03131", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b3C", + "roundness": null, + "seed": 1107965066, + "version": 79, + "versionNonce": 1846142166, + "isDeleted": false, + "boundElements": null, + "updated": 1737971535976, + "link": null, + "locked": false, + "text": "Uses", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Uses", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "RYcoP2a7h3PmEmilpAoEr", + "type": "text", + "x": 2890.400016784668, + "y": 971.5, + "width": 47.19996643066406, + "height": 25, + "angle": 0, + "strokeColor": "#e03131", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b3D", + "roundness": null, + "seed": 422145994, + "version": 82, + "versionNonce": 1186784906, + "isDeleted": false, + "boundElements": [], + "updated": 1737971541173, + "link": null, + "locked": false, + "text": "Uses", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Uses", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "JenUnqPQU9n29FUsRjstV", + "type": "arrow", + "x": 2993, + "y": 780, + "width": 828, + "height": 228, + "angle": 0, + "strokeColor": "#e03131", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b3E", + "roundness": { + "type": 2 + }, + "seed": 1211336010, + "version": 277, + "versionNonce": 439205910, + "isDeleted": false, + "boundElements": null, + "updated": 1737971555301, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -77, + 228 + ], + [ + -828, + 6 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "GdXv0Fvpyz0tdxI9bskx0", + "focus": -0.3088045944123118, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "R4AeEioM2INhMP9rnYnHe", + "focus": 0.4765988876330307, + "gap": 1, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + } + ], + "appState": { + "gridSize": 20, + "gridStep": 5, + "gridModeEnabled": false, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file diff --git a/test/multicloud/diagrams/diagram.svg b/test/multicloud/diagrams/diagram.svg new file mode 100644 index 0000000000..afa9a3c21b --- /dev/null +++ b/test/multicloud/diagrams/diagram.svg @@ -0,0 +1,2 @@ +Multi-Cloud ProjectOpenTofu IaCGO TestingFrameworkAKS KINDRetinaHelm AzureKINDGoogle CloudGKEModulesProvidersAKS KINDRetinaGKEExamplesRetina-AKSRetina-KINDRetina-GKELiveInstantiatesInstantiatesUsesUsesUsesAKS KINDRetinaGKEUnitRetina-AKS Retina-KINDRetina-GKEIntegrationUsesUses \ No newline at end of file diff --git a/test/multicloud/examples/aks/.terraform.lock.hcl b/test/multicloud/examples/aks/.terraform.lock.hcl new file mode 100644 index 0000000000..3d7443dac3 --- /dev/null +++ b/test/multicloud/examples/aks/.terraform.lock.hcl @@ -0,0 +1,20 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/hashicorp/azurerm" { + version = "4.15.0" + constraints = "4.15.0" + hashes = [ + "h1:xE74Yb3iZZF2F1hQy4B8YVCk0gLAp99pJgZX4eIXYMg=", + "zh:0a104acfc45de410d9786bdbf540009dbb7db5632fe7c6846fdb5f865007d0b4", + "zh:186f20452ca913e84de0fc9b2dc7872c6480813afe11ea076bd60c45aa2d66d0", + "zh:2d540a98254188f17d64c02847e4d178b49979871a2a05283f78d336f3f25d45", + "zh:34fdffad86800af74dd2f4c9b3a32fb4f1463ba453bb0f634a9389f503869bc6", + "zh:38751b0bb8d03c34acb63dbddf6ebe01d99e6b75a9d94ae3b3fb1c60bf43c45a", + "zh:4234e0e56e87983d387d7323d8bb49838054c5cebeb121dbb5aa4dd3255f211f", + "zh:4ead322049485495d07afe2334d82a47997fc7638b9e39512000d4499dc3a782", + "zh:74e8a9fdfbe0bb91c6542176dc14d3e95be2c3c77cca10ae57aa67116b5a6b95", + "zh:9f03e13551cd68d2f7cd2d46f74ffc33f0656e0aa8c9095ed259385aaeaf4957", + "zh:f86fce72cbdf72f52412b9099023115bece67c5df55970c4429ef0f1bdc3c473", + ] +} diff --git a/test/multicloud/examples/aks/main.tf b/test/multicloud/examples/aks/main.tf new file mode 100644 index 0000000000..c926605307 --- /dev/null +++ b/test/multicloud/examples/aks/main.tf @@ -0,0 +1,12 @@ +module "aks" { + source = "../../modules/aks" + location = var.location + resource_group_name = var.resource_group_name + prefix = var.prefix + labels = var.labels +} + +output "kubeconfig" { + value = module.aks.azure_get_kubeconfig + sensitive = true +} diff --git a/test/multicloud/examples/aks/providers.tf b/test/multicloud/examples/aks/providers.tf new file mode 100644 index 0000000000..8ec4828f25 --- /dev/null +++ b/test/multicloud/examples/aks/providers.tf @@ -0,0 +1,20 @@ +terraform { + required_version = "1.8.3" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "4.15.0" + } + } +} + +# Initialize the Azure provider +provider "azurerm" { + features { + resource_group { + prevent_deletion_if_contains_resources = false + } + } + subscription_id = var.subscription_id + tenant_id = var.tenant_id +} diff --git a/test/multicloud/examples/aks/variables.tf b/test/multicloud/examples/aks/variables.tf new file mode 100644 index 0000000000..ec3e945824 --- /dev/null +++ b/test/multicloud/examples/aks/variables.tf @@ -0,0 +1,33 @@ +variable "subscription_id" { + description = "The subscription ID for the Azure account." + type = string +} + +variable "tenant_id" { + description = "The tenant ID for the Azure account." + type = string +} + +variable "location" { + description = "The Azure Cloud location where AKS will be deployed to." + type = string + default = "UK South" +} + +variable "resource_group_name" { + description = "The name of the resource group." + type = string + default = "example-rg" +} + +variable "prefix" { + description = "A prefix to add to all resources." + type = string + default = "example-mc" +} + +variable "labels" { + description = "A map of labels to add to all resources." + type = map(string) + default = {} +} diff --git a/test/multicloud/examples/gke/.terraform.lock.hcl b/test/multicloud/examples/gke/.terraform.lock.hcl new file mode 100644 index 0000000000..f110175d5e --- /dev/null +++ b/test/multicloud/examples/gke/.terraform.lock.hcl @@ -0,0 +1,20 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/hashicorp/google" { + version = "6.17.0" + constraints = "6.17.0" + hashes = [ + "h1:aZkLSXbqbNThCCLAX1x0g8KTJANQAIosYq3xpy8JhFQ=", + "zh:0614cc52deb5914795253aecf19b4cbb5aa7e8a186839a33907ce5c35e23d537", + "zh:0b28ea31ec3b119aafc4c37a5992c29266c876db288dfc5bbfbde36631a533f1", + "zh:1b2c5df40ac55ec7c3db2b7c556ace7545fca4ccfacf605b7588a4e2be564ba8", + "zh:1db9a278cfddcaa7d9119acf231164438df07932bdabce95931a68bd3689cd39", + "zh:3729b7a9936f5ad545f7d06d11d05ce78b4bbe9941e77bf004a2b798e6a0866c", + "zh:3b7e35183a8d7980207ae7d082c490d7c2270f907e5de9e8393c6c4c32b07b3c", + "zh:581e14963dfef608285af0c08ccb5da4bdb8ae049366418d4863a4fd9fa55b74", + "zh:89d29f2d1269a30c6149bbaaae3cbe8fe0c6ed13874b77bf784ea6bbd73aee58", + "zh:c7c690c1f9fe0cbc69d4eb21727f2cf4b7ba016385184d27527d570832c393be", + "zh:dc1536fc325a0561bf0f606a38bed29e8dd2f4bec6d6e8a5301696d89c1c8079", + ] +} diff --git a/test/multicloud/examples/gke/main.tf b/test/multicloud/examples/gke/main.tf new file mode 100644 index 0000000000..daf79438c6 --- /dev/null +++ b/test/multicloud/examples/gke/main.tf @@ -0,0 +1,9 @@ +module "gke" { + source = "../../modules/gke" + location = var.location + prefix = var.prefix + project = var.project + machine_type = var.machine_type +} + +data "google_client_config" "current" {} \ No newline at end of file diff --git a/test/multicloud/examples/gke/outputs.tf b/test/multicloud/examples/gke/outputs.tf new file mode 100644 index 0000000000..1d146ecf0f --- /dev/null +++ b/test/multicloud/examples/gke/outputs.tf @@ -0,0 +1,14 @@ +output "host" { + value = module.gke.host + sensitive = true +} + +output "cluster_ca_certificate" { + value = module.gke.cluster_ca_certificate + sensitive = true +} + +output "access_token" { + value = data.google_client_config.current.access_token + sensitive = true +} \ No newline at end of file diff --git a/test/multicloud/examples/gke/providers.tf b/test/multicloud/examples/gke/providers.tf new file mode 100644 index 0000000000..f1423d15d9 --- /dev/null +++ b/test/multicloud/examples/gke/providers.tf @@ -0,0 +1,15 @@ +terraform { + required_version = "1.8.3" + required_providers { + google = { + source = "hashicorp/google" + version = "6.17.0" + } + } +} + +# Initialize the Google provider +provider "google" { + project = var.project + region = var.location +} diff --git a/test/multicloud/examples/gke/variables.tf b/test/multicloud/examples/gke/variables.tf new file mode 100644 index 0000000000..2e2da23167 --- /dev/null +++ b/test/multicloud/examples/gke/variables.tf @@ -0,0 +1,19 @@ +variable "project" { + description = "The Google Cloud project where resources will be deployed." + type = string +} + +variable "location" { + description = "The Google Cloud location where GKE will be deployed to." + type = string +} + +variable "prefix" { + description = "A prefix to add to all resources." + type = string +} + +variable "machine_type" { + description = "The machine type to use for the GKE nodes." + type = string +} diff --git a/test/multicloud/examples/integration/retina-kind/.terraform.lock.hcl b/test/multicloud/examples/integration/retina-kind/.terraform.lock.hcl new file mode 100644 index 0000000000..a641109262 --- /dev/null +++ b/test/multicloud/examples/integration/retina-kind/.terraform.lock.hcl @@ -0,0 +1,34 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/hashicorp/helm" { + version = "2.17.0" + constraints = "2.17.0" + hashes = [ + "h1:69PnHoYrrDrm7C8+8PiSvRGPI55taqL14SvQR/FGM+g=", + "zh:02690815e35131a42cb9851f63a3369c216af30ad093d05b39001d43da04b56b", + "zh:27a62f12b29926387f4d71aeeee9f7ffa0ccb81a1b6066ee895716ad050d1b7a", + "zh:2d0a5babfa73604b3fefc9dab9c87f91c77fce756c2e32b294e9f1290aed26c0", + "zh:3976400ceba6dda4636e1d297e3097e1831de5628afa534a166de98a70d1dcbe", + "zh:54440ef14f342b41d75c1aded7487bfcc3f76322b75894235b47b7e89ac4bfa4", + "zh:6512e2ab9f2fa31cbb90d9249647b5c5798f62eb1215ec44da2cdaa24e38ad25", + "zh:795f327ca0b8c5368af0ed03d5d4f6da7260692b4b3ca0bd004ed542e683464d", + "zh:ba659e1d94f224bc3f1fd34cbb9d2663e3a8e734108e5a58eb49eda84b140978", + "zh:c5c8575c4458835c2acbc3d1ed5570589b14baa2525d8fbd04295c097caf41eb", + "zh:e0877a5dac3de138e61eefa26b2f5a13305a17259779465899880f70e11314e0", + ] +} + +provider "registry.opentofu.org/tehcyx/kind" { + version = "0.7.0" + constraints = "0.7.0" + hashes = [ + "h1:nFhFHmE5+dCd9S9dEMwnMNWzyxoVipYobkhXYoDbhgA=", + "zh:171a2fb0137bfbdebd56cd65afd2e0e2167315fe4cb6a07a218db40cb17339c3", + "zh:3260b078b7997ddfd03845326ffaeed7f678eeaaf7918430356f22e299e36f22", + "zh:4066ab3feb482a0dd1bfff6590d89a0ec30478f63c9d8253cfdadb4b8db2234d", + "zh:537af73261d53f4840d1f89d8e5835c52ddb97102e6314f6aea9b8e49c43d610", + "zh:d63e94d828ba0339600d992b0a6695cff939b0aaac1c39b31d38e3c4f3823674", + "zh:f971c617bf6b37d07a5042f13a9ab02b42d0ceb14934174eecc81abeec233c40", + ] +} diff --git a/test/multicloud/examples/integration/retina-kind/main.tf b/test/multicloud/examples/integration/retina-kind/main.tf new file mode 100644 index 0000000000..8bd5749095 --- /dev/null +++ b/test/multicloud/examples/integration/retina-kind/main.tf @@ -0,0 +1,10 @@ +module "kind" { + source = "../../../modules/kind" + prefix = var.prefix +} + +module "retina" { + depends_on = [module.kind] + source = "../../../modules/retina" + retina_version = var.retina_version +} diff --git a/test/multicloud/examples/integration/retina-kind/outputs.tf b/test/multicloud/examples/integration/retina-kind/outputs.tf new file mode 100644 index 0000000000..cdc064fec7 --- /dev/null +++ b/test/multicloud/examples/integration/retina-kind/outputs.tf @@ -0,0 +1,19 @@ +output "host" { + value = module.kind.host + sensitive = true +} + +output "cluster_ca_certificate" { + value = module.kind.cluster_ca_certificate + sensitive = true +} + +output "client_certificate" { + value = module.kind.client_certificate + sensitive = true +} + +output "client_key" { + value = module.kind.client_key + sensitive = true +} diff --git a/test/multicloud/examples/integration/retina-kind/providers.tf b/test/multicloud/examples/integration/retina-kind/providers.tf new file mode 100644 index 0000000000..7b8baf2518 --- /dev/null +++ b/test/multicloud/examples/integration/retina-kind/providers.tf @@ -0,0 +1,26 @@ +terraform { + required_version = "1.8.3" + required_providers { + kind = { + source = "tehcyx/kind" + version = "0.7.0" + } + helm = { + source = "hashicorp/helm" + version = "2.17.0" + } + } +} + +# Initialize the kind provider +provider "kind" {} + +# Initialize the Helm provider +provider "helm" { + kubernetes { + host = module.kind.host + client_certificate = module.kind.client_certificate + client_key = module.kind.client_key + cluster_ca_certificate = module.kind.cluster_ca_certificate + } +} \ No newline at end of file diff --git a/test/multicloud/examples/integration/retina-kind/test-integration-kind-config b/test/multicloud/examples/integration/retina-kind/test-integration-kind-config new file mode 100644 index 0000000000..2ebf5e0ed5 --- /dev/null +++ b/test/multicloud/examples/integration/retina-kind/test-integration-kind-config @@ -0,0 +1,3 @@ +apiVersion: v1 +kind: Config +preferences: {} diff --git a/test/multicloud/examples/integration/retina-kind/test-kind-config b/test/multicloud/examples/integration/retina-kind/test-kind-config new file mode 100644 index 0000000000..2ebf5e0ed5 --- /dev/null +++ b/test/multicloud/examples/integration/retina-kind/test-kind-config @@ -0,0 +1,3 @@ +apiVersion: v1 +kind: Config +preferences: {} diff --git a/test/multicloud/examples/integration/retina-kind/variables.tf b/test/multicloud/examples/integration/retina-kind/variables.tf new file mode 100644 index 0000000000..e9d9024233 --- /dev/null +++ b/test/multicloud/examples/integration/retina-kind/variables.tf @@ -0,0 +1,11 @@ +variable "prefix" { + description = "A prefix to add to all resources." + type = string + default = "mc" +} + +variable "retina_version" { + description = "The tag to apply to all resources." + type = string + default = "v0.0.23" +} \ No newline at end of file diff --git a/test/multicloud/examples/kind/.terraform.lock.hcl b/test/multicloud/examples/kind/.terraform.lock.hcl new file mode 100644 index 0000000000..b610e36285 --- /dev/null +++ b/test/multicloud/examples/kind/.terraform.lock.hcl @@ -0,0 +1,16 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/tehcyx/kind" { + version = "0.7.0" + constraints = "0.7.0" + hashes = [ + "h1:nFhFHmE5+dCd9S9dEMwnMNWzyxoVipYobkhXYoDbhgA=", + "zh:171a2fb0137bfbdebd56cd65afd2e0e2167315fe4cb6a07a218db40cb17339c3", + "zh:3260b078b7997ddfd03845326ffaeed7f678eeaaf7918430356f22e299e36f22", + "zh:4066ab3feb482a0dd1bfff6590d89a0ec30478f63c9d8253cfdadb4b8db2234d", + "zh:537af73261d53f4840d1f89d8e5835c52ddb97102e6314f6aea9b8e49c43d610", + "zh:d63e94d828ba0339600d992b0a6695cff939b0aaac1c39b31d38e3c4f3823674", + "zh:f971c617bf6b37d07a5042f13a9ab02b42d0ceb14934174eecc81abeec233c40", + ] +} diff --git a/test/multicloud/examples/kind/main.tf b/test/multicloud/examples/kind/main.tf new file mode 100644 index 0000000000..c2484af1cb --- /dev/null +++ b/test/multicloud/examples/kind/main.tf @@ -0,0 +1,4 @@ +module "kind" { + source = "../../modules/kind" + prefix = var.prefix +} \ No newline at end of file diff --git a/test/multicloud/examples/kind/outputs.tf b/test/multicloud/examples/kind/outputs.tf new file mode 100644 index 0000000000..cdc064fec7 --- /dev/null +++ b/test/multicloud/examples/kind/outputs.tf @@ -0,0 +1,19 @@ +output "host" { + value = module.kind.host + sensitive = true +} + +output "cluster_ca_certificate" { + value = module.kind.cluster_ca_certificate + sensitive = true +} + +output "client_certificate" { + value = module.kind.client_certificate + sensitive = true +} + +output "client_key" { + value = module.kind.client_key + sensitive = true +} diff --git a/test/multicloud/examples/kind/providers.tf b/test/multicloud/examples/kind/providers.tf new file mode 100644 index 0000000000..23178d677b --- /dev/null +++ b/test/multicloud/examples/kind/providers.tf @@ -0,0 +1,12 @@ +terraform { + required_version = "1.8.3" + required_providers { + kind = { + source = "tehcyx/kind" + version = "0.7.0" + } + } +} + +# Initialize the kind provider +provider "kind" {} diff --git a/test/multicloud/examples/kind/variables.tf b/test/multicloud/examples/kind/variables.tf new file mode 100644 index 0000000000..2dd9eaf4b0 --- /dev/null +++ b/test/multicloud/examples/kind/variables.tf @@ -0,0 +1,4 @@ +variable "prefix" { + description = "A prefix to add to all resources." + type = string +} \ No newline at end of file diff --git a/test/multicloud/live/retina-aks/.terraform.lock.hcl b/test/multicloud/live/retina-aks/.terraform.lock.hcl new file mode 100644 index 0000000000..5c20d26e2a --- /dev/null +++ b/test/multicloud/live/retina-aks/.terraform.lock.hcl @@ -0,0 +1,40 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/hashicorp/azurerm" { + version = "4.15.0" + constraints = ">= 2.0.0" + hashes = [ + "h1:0YxkmS5jTUl1LIG+71sgKg/YdlgAoHNr3wyyZjJO8vY=", + "h1:xE74Yb3iZZF2F1hQy4B8YVCk0gLAp99pJgZX4eIXYMg=", + "zh:0a104acfc45de410d9786bdbf540009dbb7db5632fe7c6846fdb5f865007d0b4", + "zh:186f20452ca913e84de0fc9b2dc7872c6480813afe11ea076bd60c45aa2d66d0", + "zh:2d540a98254188f17d64c02847e4d178b49979871a2a05283f78d336f3f25d45", + "zh:34fdffad86800af74dd2f4c9b3a32fb4f1463ba453bb0f634a9389f503869bc6", + "zh:38751b0bb8d03c34acb63dbddf6ebe01d99e6b75a9d94ae3b3fb1c60bf43c45a", + "zh:4234e0e56e87983d387d7323d8bb49838054c5cebeb121dbb5aa4dd3255f211f", + "zh:4ead322049485495d07afe2334d82a47997fc7638b9e39512000d4499dc3a782", + "zh:74e8a9fdfbe0bb91c6542176dc14d3e95be2c3c77cca10ae57aa67116b5a6b95", + "zh:9f03e13551cd68d2f7cd2d46f74ffc33f0656e0aa8c9095ed259385aaeaf4957", + "zh:f86fce72cbdf72f52412b9099023115bece67c5df55970c4429ef0f1bdc3c473", + ] +} + +provider "registry.opentofu.org/hashicorp/helm" { + version = "2.17.0" + constraints = "2.17.0" + hashes = [ + "h1:69PnHoYrrDrm7C8+8PiSvRGPI55taqL14SvQR/FGM+g=", + "h1:ShIag7wqd5Rs+zYpVMpjAh+T0ozr4XGYfSTKWqceQBY=", + "zh:02690815e35131a42cb9851f63a3369c216af30ad093d05b39001d43da04b56b", + "zh:27a62f12b29926387f4d71aeeee9f7ffa0ccb81a1b6066ee895716ad050d1b7a", + "zh:2d0a5babfa73604b3fefc9dab9c87f91c77fce756c2e32b294e9f1290aed26c0", + "zh:3976400ceba6dda4636e1d297e3097e1831de5628afa534a166de98a70d1dcbe", + "zh:54440ef14f342b41d75c1aded7487bfcc3f76322b75894235b47b7e89ac4bfa4", + "zh:6512e2ab9f2fa31cbb90d9249647b5c5798f62eb1215ec44da2cdaa24e38ad25", + "zh:795f327ca0b8c5368af0ed03d5d4f6da7260692b4b3ca0bd004ed542e683464d", + "zh:ba659e1d94f224bc3f1fd34cbb9d2663e3a8e734108e5a58eb49eda84b140978", + "zh:c5c8575c4458835c2acbc3d1ed5570589b14baa2525d8fbd04295c097caf41eb", + "zh:e0877a5dac3de138e61eefa26b2f5a13305a17259779465899880f70e11314e0", + ] +} diff --git a/test/multicloud/live/retina-aks/main.tf b/test/multicloud/live/retina-aks/main.tf new file mode 100644 index 0000000000..237471fe09 --- /dev/null +++ b/test/multicloud/live/retina-aks/main.tf @@ -0,0 +1,16 @@ +module "aks" { + source = "../../modules/aks" + location = var.location + resource_group_name = var.resource_group_name + prefix = var.prefix + labels = var.labels +} + +module "retina" { + depends_on = [module.aks] + source = "../../modules/retina" +} + +output "kubeconfig_command" { + value = module.aks.azure_get_kubeconfig +} diff --git a/test/multicloud/live/retina-aks/providers.tf b/test/multicloud/live/retina-aks/providers.tf new file mode 100644 index 0000000000..264d724c95 --- /dev/null +++ b/test/multicloud/live/retina-aks/providers.tf @@ -0,0 +1,34 @@ +terraform { + required_version = "1.8.3" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "4.15.0" + } + helm = { + source = "hashicorp/helm" + version = "2.17.0" + } + } +} + +# Initialize the Azure provider +provider "azurerm" { + features { + resource_group { + prevent_deletion_if_contains_resources = false + } + } + subscription_id = var.subscription_id + tenant_id = var.tenant_id +} + +# Initialize the Helm provider +provider "helm" { + kubernetes { + host = module.aks.host + client_certificate = base64decode(module.aks.client_certificate) + client_key = base64decode(module.aks.client_key) + cluster_ca_certificate = base64decode(module.aks.cluster_ca_certificate) + } +} diff --git a/test/multicloud/live/retina-aks/variables.tf b/test/multicloud/live/retina-aks/variables.tf new file mode 100644 index 0000000000..886aacc47e --- /dev/null +++ b/test/multicloud/live/retina-aks/variables.tf @@ -0,0 +1,35 @@ +variable "subscription_id" { + description = "The subscription ID for the Azure account." + type = string +} + +variable "tenant_id" { + description = "The tenant ID for the Azure account." + type = string +} + +variable "location" { + description = "The Azure Cloud location where AKS will be deployed to." + type = string + default = "uksouth" +} + +variable "resource_group_name" { + description = "The name of the resource group." + type = string + default = "mc-rg" +} + +variable "prefix" { + description = "A prefix to add to all resources." + type = string + default = "mc" +} + +variable "labels" { + description = "A map of labels to add to all resources." + type = map(string) + default = { + "env" = "test" + } +} diff --git a/test/multicloud/live/retina-gke/.terraform.lock.hcl b/test/multicloud/live/retina-gke/.terraform.lock.hcl new file mode 100644 index 0000000000..ed3aacfe1c --- /dev/null +++ b/test/multicloud/live/retina-gke/.terraform.lock.hcl @@ -0,0 +1,40 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/hashicorp/google" { + version = "6.17.0" + constraints = ">= 6.17.0" + hashes = [ + "h1:7m+L8x7ClWUFAd4uJJENXp9O4K8HtpL50434jPR9pqs=", + "h1:aZkLSXbqbNThCCLAX1x0g8KTJANQAIosYq3xpy8JhFQ=", + "zh:0614cc52deb5914795253aecf19b4cbb5aa7e8a186839a33907ce5c35e23d537", + "zh:0b28ea31ec3b119aafc4c37a5992c29266c876db288dfc5bbfbde36631a533f1", + "zh:1b2c5df40ac55ec7c3db2b7c556ace7545fca4ccfacf605b7588a4e2be564ba8", + "zh:1db9a278cfddcaa7d9119acf231164438df07932bdabce95931a68bd3689cd39", + "zh:3729b7a9936f5ad545f7d06d11d05ce78b4bbe9941e77bf004a2b798e6a0866c", + "zh:3b7e35183a8d7980207ae7d082c490d7c2270f907e5de9e8393c6c4c32b07b3c", + "zh:581e14963dfef608285af0c08ccb5da4bdb8ae049366418d4863a4fd9fa55b74", + "zh:89d29f2d1269a30c6149bbaaae3cbe8fe0c6ed13874b77bf784ea6bbd73aee58", + "zh:c7c690c1f9fe0cbc69d4eb21727f2cf4b7ba016385184d27527d570832c393be", + "zh:dc1536fc325a0561bf0f606a38bed29e8dd2f4bec6d6e8a5301696d89c1c8079", + ] +} + +provider "registry.opentofu.org/hashicorp/helm" { + version = "2.17.0" + constraints = "2.17.0" + hashes = [ + "h1:69PnHoYrrDrm7C8+8PiSvRGPI55taqL14SvQR/FGM+g=", + "h1:ShIag7wqd5Rs+zYpVMpjAh+T0ozr4XGYfSTKWqceQBY=", + "zh:02690815e35131a42cb9851f63a3369c216af30ad093d05b39001d43da04b56b", + "zh:27a62f12b29926387f4d71aeeee9f7ffa0ccb81a1b6066ee895716ad050d1b7a", + "zh:2d0a5babfa73604b3fefc9dab9c87f91c77fce756c2e32b294e9f1290aed26c0", + "zh:3976400ceba6dda4636e1d297e3097e1831de5628afa534a166de98a70d1dcbe", + "zh:54440ef14f342b41d75c1aded7487bfcc3f76322b75894235b47b7e89ac4bfa4", + "zh:6512e2ab9f2fa31cbb90d9249647b5c5798f62eb1215ec44da2cdaa24e38ad25", + "zh:795f327ca0b8c5368af0ed03d5d4f6da7260692b4b3ca0bd004ed542e683464d", + "zh:ba659e1d94f224bc3f1fd34cbb9d2663e3a8e734108e5a58eb49eda84b140978", + "zh:c5c8575c4458835c2acbc3d1ed5570589b14baa2525d8fbd04295c097caf41eb", + "zh:e0877a5dac3de138e61eefa26b2f5a13305a17259779465899880f70e11314e0", + ] +} diff --git a/test/multicloud/live/retina-gke/main.tf b/test/multicloud/live/retina-gke/main.tf new file mode 100644 index 0000000000..de30d24493 --- /dev/null +++ b/test/multicloud/live/retina-gke/main.tf @@ -0,0 +1,12 @@ +module "gke" { + source = "../../modules/gke" + location = var.location + prefix = var.prefix + project = var.project + machine_type = var.machine_type +} + +module "retina" { + depends_on = [module.gke] + source = "../../modules/retina" +} diff --git a/test/multicloud/live/retina-gke/outputs.tf b/test/multicloud/live/retina-gke/outputs.tf new file mode 100644 index 0000000000..1954916e98 --- /dev/null +++ b/test/multicloud/live/retina-gke/outputs.tf @@ -0,0 +1,3 @@ +output "kubeconfig_command" { + value = module.gke.gcloud_get_kubeconfig +} diff --git a/test/multicloud/live/retina-gke/providers.tf b/test/multicloud/live/retina-gke/providers.tf new file mode 100644 index 0000000000..ac23c59c0e --- /dev/null +++ b/test/multicloud/live/retina-gke/providers.tf @@ -0,0 +1,30 @@ +terraform { + required_version = "1.8.3" + required_providers { + google = { + source = "hashicorp/google" + version = "6.17.0" + } + helm = { + source = "hashicorp/helm" + version = "2.17.0" + } + } +} + +# Initialize the Google provider +provider "google" { + project = var.project + region = var.location +} + +data "google_client_config" "current" {} + +# Initialize the Helm provider +provider "helm" { + kubernetes { + token = data.google_client_config.current.access_token + host = module.gke.host + cluster_ca_certificate = base64decode(module.gke.cluster_ca_certificate) + } +} \ No newline at end of file diff --git a/test/multicloud/live/retina-gke/variables.tf b/test/multicloud/live/retina-gke/variables.tf new file mode 100644 index 0000000000..9e00f0f537 --- /dev/null +++ b/test/multicloud/live/retina-gke/variables.tf @@ -0,0 +1,23 @@ +variable "project" { + description = "The Google Cloud project where resources will be deployed." + type = string + default = "mc-retina" +} + +variable "location" { + description = "The Google Cloud location where GKE will be deployed to." + type = string + default = "eu-central1" +} + +variable "prefix" { + description = "A prefix to add to all resources." + type = string + default = "mc" +} + +variable "machine_type" { + description = "The machine type to use for the GKE nodes." + type = string + default = "e2-standard-4" +} diff --git a/test/multicloud/live/retina-kind/.terraform.lock.hcl b/test/multicloud/live/retina-kind/.terraform.lock.hcl new file mode 100644 index 0000000000..afc28ace1d --- /dev/null +++ b/test/multicloud/live/retina-kind/.terraform.lock.hcl @@ -0,0 +1,36 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/hashicorp/helm" { + version = "2.17.0" + constraints = "2.17.0" + hashes = [ + "h1:69PnHoYrrDrm7C8+8PiSvRGPI55taqL14SvQR/FGM+g=", + "h1:ShIag7wqd5Rs+zYpVMpjAh+T0ozr4XGYfSTKWqceQBY=", + "zh:02690815e35131a42cb9851f63a3369c216af30ad093d05b39001d43da04b56b", + "zh:27a62f12b29926387f4d71aeeee9f7ffa0ccb81a1b6066ee895716ad050d1b7a", + "zh:2d0a5babfa73604b3fefc9dab9c87f91c77fce756c2e32b294e9f1290aed26c0", + "zh:3976400ceba6dda4636e1d297e3097e1831de5628afa534a166de98a70d1dcbe", + "zh:54440ef14f342b41d75c1aded7487bfcc3f76322b75894235b47b7e89ac4bfa4", + "zh:6512e2ab9f2fa31cbb90d9249647b5c5798f62eb1215ec44da2cdaa24e38ad25", + "zh:795f327ca0b8c5368af0ed03d5d4f6da7260692b4b3ca0bd004ed542e683464d", + "zh:ba659e1d94f224bc3f1fd34cbb9d2663e3a8e734108e5a58eb49eda84b140978", + "zh:c5c8575c4458835c2acbc3d1ed5570589b14baa2525d8fbd04295c097caf41eb", + "zh:e0877a5dac3de138e61eefa26b2f5a13305a17259779465899880f70e11314e0", + ] +} + +provider "registry.opentofu.org/tehcyx/kind" { + version = "0.7.0" + constraints = "0.7.0" + hashes = [ + "h1:9ci1+3JBxvMRZ0pnzoVNmw7NrBCAfzqOPyhm+I8Rxag=", + "h1:nFhFHmE5+dCd9S9dEMwnMNWzyxoVipYobkhXYoDbhgA=", + "zh:171a2fb0137bfbdebd56cd65afd2e0e2167315fe4cb6a07a218db40cb17339c3", + "zh:3260b078b7997ddfd03845326ffaeed7f678eeaaf7918430356f22e299e36f22", + "zh:4066ab3feb482a0dd1bfff6590d89a0ec30478f63c9d8253cfdadb4b8db2234d", + "zh:537af73261d53f4840d1f89d8e5835c52ddb97102e6314f6aea9b8e49c43d610", + "zh:d63e94d828ba0339600d992b0a6695cff939b0aaac1c39b31d38e3c4f3823674", + "zh:f971c617bf6b37d07a5042f13a9ab02b42d0ceb14934174eecc81abeec233c40", + ] +} diff --git a/test/multicloud/live/retina-kind/main.tf b/test/multicloud/live/retina-kind/main.tf new file mode 100644 index 0000000000..6f71163ccf --- /dev/null +++ b/test/multicloud/live/retina-kind/main.tf @@ -0,0 +1,9 @@ +module "kind" { + source = "../../modules/kind" + prefix = var.prefix +} + +module "retina" { + depends_on = [module.kind] + source = "../../modules/retina" +} diff --git a/test/multicloud/live/retina-kind/providers.tf b/test/multicloud/live/retina-kind/providers.tf new file mode 100644 index 0000000000..7b8baf2518 --- /dev/null +++ b/test/multicloud/live/retina-kind/providers.tf @@ -0,0 +1,26 @@ +terraform { + required_version = "1.8.3" + required_providers { + kind = { + source = "tehcyx/kind" + version = "0.7.0" + } + helm = { + source = "hashicorp/helm" + version = "2.17.0" + } + } +} + +# Initialize the kind provider +provider "kind" {} + +# Initialize the Helm provider +provider "helm" { + kubernetes { + host = module.kind.host + client_certificate = module.kind.client_certificate + client_key = module.kind.client_key + cluster_ca_certificate = module.kind.cluster_ca_certificate + } +} \ No newline at end of file diff --git a/test/multicloud/live/retina-kind/variables.tf b/test/multicloud/live/retina-kind/variables.tf new file mode 100644 index 0000000000..347514bd40 --- /dev/null +++ b/test/multicloud/live/retina-kind/variables.tf @@ -0,0 +1,5 @@ +variable "prefix" { + description = "A prefix to add to all resources." + type = string + default = "mc" +} \ No newline at end of file diff --git a/test/multicloud/modules/aks/main.tf b/test/multicloud/modules/aks/main.tf new file mode 100644 index 0000000000..a7352bd589 --- /dev/null +++ b/test/multicloud/modules/aks/main.tf @@ -0,0 +1,47 @@ +resource "azurerm_resource_group" "aks_rg" { + name = var.resource_group_name + location = var.location +} + +resource "azurerm_kubernetes_cluster" "aks" { + name = "${var.prefix}-aks" + location = azurerm_resource_group.aks_rg.location + resource_group_name = azurerm_resource_group.aks_rg.name + dns_prefix = "${var.prefix}-aks-dns" + kubernetes_version = var.kubernetes_version + + dynamic "default_node_pool" { + for_each = [var.default_node_pool] + content { + name = default_node_pool.value.name + node_count = default_node_pool.value.node_count + vm_size = default_node_pool.value.vm_size + os_disk_size_gb = default_node_pool.value.os_disk_size_gb + os_disk_type = default_node_pool.value.os_disk_type + max_pods = default_node_pool.value.max_pods + type = default_node_pool.value.type + node_labels = default_node_pool.value.node_labels + } + } + + identity { + type = "SystemAssigned" + } + + dynamic "network_profile" { + for_each = [var.network_profile] + content { + network_plugin = network_profile.value.network_plugin + network_plugin_mode = network_profile.value.network_plugin_mode + load_balancer_profile { + managed_outbound_ip_count = network_profile.value.load_balancer_profile.managed_outbound_ip_count + } + pod_cidr = network_profile.value.pod_cidr + service_cidr = network_profile.value.service_cidr + dns_service_ip = network_profile.value.dns_service_ip + outbound_type = network_profile.value.outbound_type + } + } + + tags = var.labels +} diff --git a/test/multicloud/modules/aks/outputs.tf b/test/multicloud/modules/aks/outputs.tf new file mode 100644 index 0000000000..e71ca414ff --- /dev/null +++ b/test/multicloud/modules/aks/outputs.tf @@ -0,0 +1,24 @@ +output "azure_get_kubeconfig" { + value = "az aks get-credentials --resource-group ${azurerm_resource_group.aks_rg.name} --name ${azurerm_kubernetes_cluster.aks.name} --admin" + description = "Run this command to fetch the kubeconfig for your AKS cluster" +} + +output "host" { + value = azurerm_kubernetes_cluster.aks.kube_config.0.host + sensitive = true +} + +output "client_certificate" { + value = azurerm_kubernetes_cluster.aks.kube_config.0.client_certificate + sensitive = true +} + +output "client_key" { + value = azurerm_kubernetes_cluster.aks.kube_config.0.client_key + sensitive = true +} + +output "cluster_ca_certificate" { + value = azurerm_kubernetes_cluster.aks.kube_config.0.cluster_ca_certificate + sensitive = true +} diff --git a/test/multicloud/modules/aks/provider.tf b/test/multicloud/modules/aks/provider.tf new file mode 100644 index 0000000000..33705925cf --- /dev/null +++ b/test/multicloud/modules/aks/provider.tf @@ -0,0 +1,9 @@ +terraform { + required_version = "1.8.3" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "4.15.0" + } + } +} diff --git a/test/multicloud/modules/aks/variables.tf b/test/multicloud/modules/aks/variables.tf new file mode 100644 index 0000000000..d5a5ebb597 --- /dev/null +++ b/test/multicloud/modules/aks/variables.tf @@ -0,0 +1,78 @@ +variable "location" { + description = "The VM location." + type = string + default = "UK South" +} + +variable "resource_group_name" { + description = "The name of the resource group." + type = string +} + +variable "prefix" { + description = "A prefix to add to all resources." + type = string + default = "example-vm" +} + +variable "labels" { + description = "A map of labels to add to all resources." + type = map(string) + default = {} +} + +variable "network_profile" { + description = "Network profile configuration" + type = object({ + network_plugin = string + network_plugin_mode = string + load_balancer_profile = object({ + managed_outbound_ip_count = number + }) + pod_cidr = string + service_cidr = string + dns_service_ip = string + outbound_type = string + }) + default = { + network_plugin = "azure" + network_plugin_mode = "overlay" + load_balancer_profile = { + managed_outbound_ip_count = 1 + } + pod_cidr = "10.244.0.0/16" + service_cidr = "10.0.0.0/16" + dns_service_ip = "10.0.0.10" + outbound_type = "loadBalancer" + } +} + +variable "default_node_pool" { + description = "Default node pool configuration" + type = object({ + name = string + node_count = number + vm_size = string + os_disk_size_gb = number + os_disk_type = string + max_pods = number + type = string + node_labels = map(string) + }) + default = { + name = "agentpool" + node_count = 2 + vm_size = "Standard_D4ds_v5" + os_disk_size_gb = 128 + os_disk_type = "Ephemeral" + max_pods = 110 + type = "VirtualMachineScaleSets" + node_labels = {} + } +} + +variable "kubernetes_version" { + description = "The version of Kubernetes to use for the AKS cluster." + type = string + default = "1.29.8" +} diff --git a/test/multicloud/modules/gke/main.tf b/test/multicloud/modules/gke/main.tf new file mode 100644 index 0000000000..c4615b7858 --- /dev/null +++ b/test/multicloud/modules/gke/main.tf @@ -0,0 +1,34 @@ +resource "google_service_account" "default" { + account_id = "${var.prefix}-gke-service-account" + display_name = "GKE Service Account for ${var.project}" +} + +resource "google_container_cluster" "gke" { + name = "${var.prefix}-gke-cluster" + location = var.location + + # We can't create a cluster with no node pool defined, but we want to only use + # separately managed node pools. So we create the smallest possible default + # node pool and immediately delete it. + remove_default_node_pool = true + initial_node_count = 1 + deletion_protection = false +} + +resource "google_container_node_pool" "gke_preemptible_nodes" { + name = "${var.prefix}-node-pool" + location = var.location + cluster = google_container_cluster.gke.name + node_count = 1 + + node_config { + preemptible = true + machine_type = var.machine_type + + # Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles. + service_account = google_service_account.default.email + oauth_scopes = [ + "https://www.googleapis.com/auth/cloud-platform" + ] + } +} \ No newline at end of file diff --git a/test/multicloud/modules/gke/output.tf b/test/multicloud/modules/gke/output.tf new file mode 100644 index 0000000000..692cb7eddf --- /dev/null +++ b/test/multicloud/modules/gke/output.tf @@ -0,0 +1,14 @@ +output "gcloud_get_kubeconfig" { + value = "gcloud container clusters get-credentials ${google_container_cluster.gke.name} --region ${google_container_cluster.gke.location} --project ${google_container_cluster.gke.project}" + description = "Run this command to fetch the kubeconfig for your GKE cluster" +} + +output "host" { + value = "https://${google_container_cluster.gke.endpoint}" + sensitive = true +} + +output "cluster_ca_certificate" { + value = google_container_cluster.gke.master_auth.0.cluster_ca_certificate + sensitive = true +} \ No newline at end of file diff --git a/test/multicloud/modules/gke/provider.tf b/test/multicloud/modules/gke/provider.tf new file mode 100644 index 0000000000..dbf7e91ddc --- /dev/null +++ b/test/multicloud/modules/gke/provider.tf @@ -0,0 +1,9 @@ +terraform { + required_version = "1.8.3" + required_providers { + google = { + source = "hashicorp/google" + version = "6.17.0" + } + } +} \ No newline at end of file diff --git a/test/multicloud/modules/gke/variables.tf b/test/multicloud/modules/gke/variables.tf new file mode 100644 index 0000000000..9971acce00 --- /dev/null +++ b/test/multicloud/modules/gke/variables.tf @@ -0,0 +1,19 @@ +variable "project" { + description = "The Google Cloud project where resources will be deployed." + type = string +} + +variable "location" { + description = "The Google Cloud location where GKE will be deployed to." + type = string +} + +variable "prefix" { + description = "A prefix to add to all resources." + type = string +} + +variable "machine_type" { + description = "The machine type to use for the GKE nodes." + type = string +} \ No newline at end of file diff --git a/test/multicloud/modules/kind/main.tf b/test/multicloud/modules/kind/main.tf new file mode 100644 index 0000000000..42b66b4b7b --- /dev/null +++ b/test/multicloud/modules/kind/main.tf @@ -0,0 +1,20 @@ +resource "kind_cluster" "kind" { + name = "${var.prefix}-kind" + wait_for_ready = true + kind_config { + kind = "Cluster" + api_version = "kind.x-k8s.io/v1alpha4" + + node { + role = "control-plane" + } + + node { + role = "worker" + } + + node { + role = "worker" + } + } +} \ No newline at end of file diff --git a/test/multicloud/modules/kind/output.tf b/test/multicloud/modules/kind/output.tf new file mode 100644 index 0000000000..1b5b5f3698 --- /dev/null +++ b/test/multicloud/modules/kind/output.tf @@ -0,0 +1,24 @@ +output "kubeconfig" { + value = kind_cluster.kind.kubeconfig + sensitive = true +} + +output "host" { + value = kind_cluster.kind.endpoint + sensitive = true +} + +output "client_certificate" { + value = kind_cluster.kind.client_certificate + sensitive = true +} + +output "client_key" { + value = kind_cluster.kind.client_key + sensitive = true +} + +output "cluster_ca_certificate" { + value = kind_cluster.kind.cluster_ca_certificate + sensitive = true +} \ No newline at end of file diff --git a/test/multicloud/modules/kind/provider.tf b/test/multicloud/modules/kind/provider.tf new file mode 100644 index 0000000000..9a655cac22 --- /dev/null +++ b/test/multicloud/modules/kind/provider.tf @@ -0,0 +1,9 @@ +terraform { + required_version = "1.8.3" + required_providers { + kind = { + source = "tehcyx/kind" + version = "0.7.0" + } + } +} \ No newline at end of file diff --git a/test/multicloud/modules/kind/variables.tf b/test/multicloud/modules/kind/variables.tf new file mode 100644 index 0000000000..2dd9eaf4b0 --- /dev/null +++ b/test/multicloud/modules/kind/variables.tf @@ -0,0 +1,4 @@ +variable "prefix" { + description = "A prefix to add to all resources." + type = string +} \ No newline at end of file diff --git a/test/multicloud/modules/retina/main.tf b/test/multicloud/modules/retina/main.tf new file mode 100644 index 0000000000..3d0d0f3400 --- /dev/null +++ b/test/multicloud/modules/retina/main.tf @@ -0,0 +1,15 @@ +resource "helm_release" "retina" { + name = "retina" + repository = "oci://ghcr.io/microsoft/retina/charts" + chart = "retina" + version = var.retina_version + namespace = "kube-system" + + dynamic "set" { + for_each = var.values + content { + name = set.value.name + value = set.value.value + } + } +} diff --git a/test/multicloud/modules/retina/provider.tf b/test/multicloud/modules/retina/provider.tf new file mode 100644 index 0000000000..83de5829ac --- /dev/null +++ b/test/multicloud/modules/retina/provider.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + helm = { + source = "hashicorp/helm" + version = "2.17.0" + } + } +} diff --git a/test/multicloud/modules/retina/variables.tf b/test/multicloud/modules/retina/variables.tf new file mode 100644 index 0000000000..daaa2b717e --- /dev/null +++ b/test/multicloud/modules/retina/variables.tf @@ -0,0 +1,27 @@ +variable "retina_version" { + description = "The tag to apply to all resources." + type = string + default = "v0.0.23" +} + +variable "values" { + description = "Configuration for set blocks, this corresponds to Helm values.yaml" + type = list(object({ + name = string + value = string + })) + default = [ + { + name = "image.tag" + value = "v0.0.23" + }, + { + name = "operator.tag" + value = "v0.0.23" + }, + { + name = "logLevel" + value = "info" + } + ] +} diff --git a/test/multicloud/test/example_aks_test.go b/test/multicloud/test/example_aks_test.go new file mode 100644 index 0000000000..7bbdf6fa4d --- /dev/null +++ b/test/multicloud/test/example_aks_test.go @@ -0,0 +1,38 @@ +package test + +import ( + "testing" + + "github.com/gruntwork-io/terratest/modules/terraform" +) + +func TestAKSExample(t *testing.T) { + t.Parallel() + + opts := &terraform.Options{ + TerraformDir: "../examples/aks", + + Vars: map[string]interface{}{ + "prefix": "test", + "location": "uksouth", + "subscription_id": "d6050d84-e4dd-463d-afc7-a6ab3dc33ab7", // TODO: replace with actual project once we get azure "public" access + "tenant_id": "ac8a4ccd-35f1-4f95-a688-f68e3d89adfc", + "resource_group_name": "test", + "labels": map[string]string{ + "environment": "test", + "owner": "test", + "project": "test", + }, + }, + } + + // clean up at the end of the test + defer terraform.Destroy(t, opts) + + terraform.Init(t, opts) + + // TODO: uncomment once we get creds for azure "public" + // terraform.Apply(t, opts) + + // TODO: add actual tests here +} diff --git a/test/multicloud/test/example_gke_test.go b/test/multicloud/test/example_gke_test.go new file mode 100644 index 0000000000..2f9980d0e8 --- /dev/null +++ b/test/multicloud/test/example_gke_test.go @@ -0,0 +1,54 @@ +package test + +import ( + "testing" + + "github.com/gruntwork-io/terratest/modules/terraform" +) + +func TestGKEExample(t *testing.T) { + t.Parallel() + + opts := &terraform.Options{ + TerraformDir: "../examples/gke", + + Vars: map[string]interface{}{ + "prefix": "test", + "location": "europe-west2", // London + "project": "mc-retina", // TODO: replace with actual project once we get gcloud access + "machine_type": "e2-standard-4", + }, + } + + // clean up at the end of the test + defer terraform.Destroy(t, opts) + + terraform.Init(t, opts) + + // TODO: uncomment once we get creds for gcloud + // terraform.Apply(t, opts) + + // // get outputs + // caCert := terraform.Output(t, opts, "cluster_ca_certificate") + // host := terraform.Output(t, opts, "host") + // token := terraform.Output(t, opts, "access_token") + + // caCertString, err := decodeBase64(caCert) + // if err != nil { + // t.Fatalf("Failed to decode ca cert: %v", err) + // } + + // // build the REST config + // restConfig := createRESTConfigWithBearer(caCertString, token, host) + + // // create a Kubernetes clientset + // clientSet, err := buildClientSet(restConfig) + // if err != nil { + // t.Fatalf("Failed to create Kubernetes clientset: %v", err) + // } + + // // test the cluster is accessible + // testClusterAccess(t, clientSet) + + // // TODO: add more tests here +} diff --git a/test/multicloud/test/example_kind_test.go b/test/multicloud/test/example_kind_test.go new file mode 100644 index 0000000000..f16affa4dd --- /dev/null +++ b/test/multicloud/test/example_kind_test.go @@ -0,0 +1,43 @@ +package test + +import ( + "testing" + + "github.com/gruntwork-io/terratest/modules/terraform" +) + +func TestKindExample(t *testing.T) { + t.Parallel() + + opts := &terraform.Options{ + TerraformDir: "../examples/kind", + + Vars: map[string]interface{}{ + "prefix": "test", + }, + } + + // clean up at the end of the test + defer terraform.Destroy(t, opts) + + terraform.Init(t, opts) + terraform.Apply(t, opts) + + // get outputs + caCert := terraform.Output(t, opts, "cluster_ca_certificate") + clientCert := terraform.Output(t, opts, "client_certificate") + clientKey := terraform.Output(t, opts, "client_key") + host := terraform.Output(t, opts, "host") + + // build the REST config + restConfig := createRESTConfigWithClientCert(caCert, clientCert, clientKey, host) + + // create a Kubernetes clientset + clientSet, err := buildClientSet(restConfig) + if err != nil { + t.Fatalf("Failed to create Kubernetes clientset: %v", err) + } + + // test the cluster is accessible + testClusterAccess(t, clientSet) +} diff --git a/test/multicloud/test/go.mod b/test/multicloud/test/go.mod new file mode 100644 index 0000000000..e768135864 --- /dev/null +++ b/test/multicloud/test/go.mod @@ -0,0 +1,73 @@ +module github.com/microsoft/retina/test/multicloud/test + +go 1.23.4 + +require ( + github.com/agext/levenshtein v1.2.3 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gruntwork-io/terratest v0.48.1 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-getter/v2 v2.2.3 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-safetemp v1.0.0 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect + github.com/hashicorp/hcl/v2 v2.22.0 // indirect + github.com/hashicorp/terraform-json v0.23.0 // indirect + github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.16.5 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/stretchr/testify v1.9.0 // indirect + github.com/tmccombs/hcl2json v0.6.4 // indirect + github.com/ulikunitz/xz v0.5.10 // indirect + github.com/x448/float16 v0.8.4 // indirect + github.com/zclconf/go-cty v1.15.0 // indirect + golang.org/x/crypto v0.29.0 // indirect + golang.org/x/mod v0.21.0 // indirect + golang.org/x/net v0.31.0 // indirect + golang.org/x/oauth2 v0.24.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/term v0.26.0 // indirect + golang.org/x/text v0.20.0 // indirect + golang.org/x/time v0.8.0 // indirect + golang.org/x/tools v0.26.0 // indirect + google.golang.org/protobuf v1.35.1 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.32.1 // indirect + k8s.io/apimachinery v0.32.1 // indirect + k8s.io/client-go v0.32.1 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect + k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect + sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect +) diff --git a/test/multicloud/test/go.sum b/test/multicloud/test/go.sum new file mode 100644 index 0000000000..9990bc6862 --- /dev/null +++ b/test/multicloud/test/go.sum @@ -0,0 +1,192 @@ +github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gruntwork-io/terratest v0.48.1 h1:pnydDjkWbZCUYXvQkr24y21fBo8PfJC5hRGdwbl1eXM= +github.com/gruntwork-io/terratest v0.48.1/go.mod h1:U2EQW4Odlz75XJUH16Kqkr9c93p+ZZtkpVez7GkZFa4= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-getter/v2 v2.2.3 h1:6CVzhT0KJQHqd9b0pK3xSP0CM/Cv+bVhk+jcaRJ2pGk= +github.com/hashicorp/go-getter/v2 v2.2.3/go.mod h1:hp5Yy0GMQvwWVUmwLs3ygivz1JSLI323hdIE9J9m7TY= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= +github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/hcl/v2 v2.22.0 h1:hkZ3nCtqeJsDhPRFz5EA9iwcG1hNWGePOTw6oyul12M= +github.com/hashicorp/hcl/v2 v2.22.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA= +github.com/hashicorp/terraform-json v0.23.0 h1:sniCkExU4iKtTADReHzACkk8fnpQXrdD2xoR+lppBkI= +github.com/hashicorp/terraform-json v0.23.0/go.mod h1:MHdXbBAbSg0GvzuWazEGKAn/cyNfIB7mN6y7KJN6y2c= +github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a h1:zPPuIq2jAWWPTrGt70eK/BSch+gFAGrNzecsoENgu2o= +github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= +github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 h1:ofNAzWCcyTALn2Zv40+8XitdzCgXY6e9qvXwN9W0YXg= +github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tmccombs/hcl2json v0.6.4 h1:/FWnzS9JCuyZ4MNwrG4vMrFrzRgsWEOVi+1AyYUVLGw= +github.com/tmccombs/hcl2json v0.6.4/go.mod h1:+ppKlIW3H5nsAsZddXPy2iMyvld3SHxyjswOZhavRDk= +github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= +github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ= +github.com/zclconf/go-cty v1.15.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc= +k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k= +k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs= +k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU= +k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= +k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= +sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= +sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/test/multicloud/test/integration_retina_kind_test.go b/test/multicloud/test/integration_retina_kind_test.go new file mode 100644 index 0000000000..110f6dc191 --- /dev/null +++ b/test/multicloud/test/integration_retina_kind_test.go @@ -0,0 +1,49 @@ +package test + +import ( + "testing" + + "github.com/gruntwork-io/terratest/modules/terraform" +) + +func TestRetinaKindIntegration(t *testing.T) { + t.Parallel() + + opts := &terraform.Options{ + TerraformDir: "../examples/integration/retina-kind", + + Vars: map[string]interface{}{ + "prefix": "test-integration", + "retina_version": "v0.0.24", + }, + } + + // clean up at the end of the test + defer terraform.Destroy(t, opts) + + terraform.Init(t, opts) + terraform.Apply(t, opts) + + // get outputs + caCert := terraform.Output(t, opts, "cluster_ca_certificate") + clientCert := terraform.Output(t, opts, "client_certificate") + clientKey := terraform.Output(t, opts, "client_key") + host := terraform.Output(t, opts, "host") + + // build the REST config + restConfig := createRESTConfigWithClientCert(caCert, clientCert, clientKey, host) + + // create a Kubernetes clientset + clientSet, err := buildClientSet(restConfig) + if err != nil { + t.Fatalf("Failed to create Kubernetes clientset: %v", err) + } + + // test the cluster is accessible + testClusterAccess(t, clientSet) + + // check the retina pods logs for errors + checkRetinaLogs(t, clientSet) + + // TODO: add more tests here +} diff --git a/test/multicloud/test/testUtils.go b/test/multicloud/test/testUtils.go new file mode 100644 index 0000000000..dd1e24924e --- /dev/null +++ b/test/multicloud/test/testUtils.go @@ -0,0 +1,120 @@ +package test + +import ( + "bufio" + "context" + "encoding/base64" + "fmt" + "io" + "strings" + "testing" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" +) + +func buildClientSet(config *rest.Config) (*kubernetes.Clientset, error) { + // Create a Kubernetes client + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + return nil, err + } + return clientset, nil +} + +// Create a Bearer token REST config +func createRESTConfigWithBearer(caCert, bearerToken, host string) *rest.Config { + config := &rest.Config{ + Host: host, + BearerToken: bearerToken, + TLSClientConfig: rest.TLSClientConfig{ + CAData: []byte(caCert), + }, + } + return config +} + +// Create REST config with client cert and key +func createRESTConfigWithClientCert(caCert, clientCert, clientKey, host string) *rest.Config { + config := &rest.Config{ + Host: host, + TLSClientConfig: rest.TLSClientConfig{ + CAData: []byte(caCert), + CertData: []byte(clientCert), + KeyData: []byte(clientKey), + }, + } + return config +} + +func testClusterAccess(t *testing.T, clientset *kubernetes.Clientset) { + // Test the cluster is accessible by listing nodes + _, err := clientset.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) + if err != nil { + t.Fatalf("Failed to list nodes: %v", err) + } + // Test the cluster is accessible by listing namespaces + _, err = clientset.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{}) + if err != nil { + t.Fatalf("Failed to list namespaces: %v", err) + } +} + +func checkLogsForErrors(logs io.ReadCloser) error { + scanner := bufio.NewScanner(logs) + for scanner.Scan() { + line := scanner.Text() + // print a debug line + fmt.Printf("Log line: %s\n", line) + // Check if the line contains the word "error" + if strings.Contains(strings.ToLower(line), "error") { + // create a new error with the log line + return fmt.Errorf("Error found in logs: %s", line) + } + } + // Check for any scanner errors + if err := scanner.Err(); err != nil { + return err + } + return nil +} + +func checkRetinaLogs(t *testing.T, clientset *kubernetes.Clientset) { + // Get the logs for the retina pods + pods, err := clientset.CoreV1().Pods("kube-system").List(context.TODO(), metav1.ListOptions{ + LabelSelector: "k8s-app=retina", + }) + if err != nil { + t.Fatalf("Failed to list pods: %v", err) + } + // Stream the logs for each pod + for _, pod := range pods.Items { + // Get the logs for the pod + req := clientset.CoreV1().Pods("kube-system").GetLogs(pod.Name, &v1.PodLogOptions{}) + // Stream the logs + logs, err := req.Stream(context.Background()) + if err != nil { + t.Fatalf("Failed to get logs for pod %s: %v", pod.Name, err) + } + // Check the logs for errors + err = checkLogsForErrors(logs) + if err != nil { + t.Fatalf("Failed to check logs for errors: %v", err) + } + // Close the logs stream + logs.Close() + } +} + +// function to convert base64 encoded string to plain text +func decodeBase64(encoded string) (string, error) { + // decode the base64 encoded string + decoded, err := base64.StdEncoding.DecodeString(encoded) + if err != nil { + return "", err + } + // return the decoded string + return string(decoded), nil +}